diff --git a/package/MDAnalysis/coordinates/CRD.py b/package/MDAnalysis/coordinates/CRD.py index c57d9dea0d..e762c83767 100644 --- a/package/MDAnalysis/coordinates/CRD.py +++ b/package/MDAnalysis/coordinates/CRD.py @@ -45,8 +45,9 @@ class CRDReader(base.SingleFrameReaderBase): Now returns a ValueError instead of FormatError. Frames now 0-based instead of 1-based. """ - format = 'CRD' - units = {'time': None, 'length': 'Angstrom'} + + format = "CRD" + units = {"time": None, "length": "Angstrom"} def _read_first_frame(self): # EXT: @@ -62,37 +63,47 @@ def _read_first_frame(self): extended = False natoms = 0 for linenum, line in enumerate(crdfile): - if line.strip().startswith('*') or line.strip() == "": + if line.strip().startswith("*") or line.strip() == "": continue # ignore TITLE and empty lines fields = line.split() if len(fields) <= 2: # should be the natoms line natoms = int(fields[0]) - extended = (fields[-1] == 'EXT') + extended = fields[-1] == "EXT" continue # process coordinates try: if extended: - coords_list.append(np.array(line[45:100].split()[0:3], dtype=float)) + coords_list.append( + np.array(line[45:100].split()[0:3], dtype=float) + ) else: - coords_list.append(np.array(line[20:50].split()[0:3], dtype=float)) + coords_list.append( + 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) - self.ts = self._Timestep.from_coordinates(np.array(coords_list), - **self._ts_kwargs) + self.ts = self._Timestep.from_coordinates( + np.array(coords_list), **self._ts_kwargs + ) self.ts.frame = 0 # 0-based frame number # if self.convert_units: # self.convert_pos_from_native(self.ts._pos) # in-place ! # sanity check 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)) + raise ValueError( + "Found %d coordinates in %r but the header claims that there " + "should be %d coordinates." + % (self.n_atoms, self.filename, natoms) + ) def Writer(self, filename, **kwargs): """Returns a CRDWriter for *filename*. @@ -132,21 +143,26 @@ class CRDWriter(base.WriterBase): Files are now written in `wt` mode, and keep extensions, allowing for files to be written under compressed formats """ - format = 'CRD' - units = {'time': None, 'length': 'Angstrom'} + + format = "CRD" + units = {"time": None, "length": "Angstrom"} fmt = { - #crdtype = 'extended' - #fortran_format = '(2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10)' - "ATOM_EXT": ("{serial:10d}{totRes:10d} {resname:<8.8s} {name:<8.8s}" - "{pos[0]:20.10f}{pos[1]:20.10f}{pos[2]:20.10f} " - "{chainID:<8.8s} {resSeq:<8d}{tempfactor:20.10f}\n"), + # crdtype = 'extended' + # fortran_format = '(2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10)' + "ATOM_EXT": ( + "{serial:10d}{totRes:10d} {resname:<8.8s} {name:<8.8s}" + "{pos[0]:20.10f}{pos[1]:20.10f}{pos[2]:20.10f} " + "{chainID:<8.8s} {resSeq:<8d}{tempfactor:20.10f}\n" + ), "NUMATOMS_EXT": "{0:10d} EXT\n", - #crdtype = 'standard' - #fortran_format = '(2I5,1X,A4,1X,A4,3F10.5,1X,A4,1X,A4,F10.5)' - "ATOM": ("{serial:5d}{totRes:5d} {resname:<4.4s} {name:<4.4s}" - "{pos[0]:10.5f}{pos[1]:10.5f}{pos[2]:10.5f} " - "{chainID:<4.4s} {resSeq:<4d}{tempfactor:10.5f}\n"), + # crdtype = 'standard' + # fortran_format = '(2I5,1X,A4,1X,A4,3F10.5,1X,A4,1X,A4,F10.5)' + "ATOM": ( + "{serial:5d}{totRes:5d} {resname:<4.4s} {name:<4.4s}" + "{pos[0]:10.5f}{pos[1]:10.5f}{pos[2]:10.5f} " + "{chainID:<4.4s} {resSeq:<4d}{tempfactor:10.5f}\n" + ), "TITLE": "* FRAME {frame} FROM {where}\n", "NUMATOMS": "{0:5d}\n", } @@ -168,7 +184,7 @@ def __init__(self, filename, **kwargs): .. versionadded:: 2.2.0 """ - self.filename = util.filename(filename, ext='crd', keep=True) + self.filename = util.filename(filename, ext="crd", keep=True) self.crd = None # account for explicit crd format, if requested @@ -200,21 +216,22 @@ def write(self, selection, frame=None): except AttributeError: 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) # *len refers to how to truncate various things, # depending on output format! if self.extended or n_atoms > 99999: - at_fmt = self.fmt['ATOM_EXT'] + at_fmt = self.fmt["ATOM_EXT"] serial_len = 10 resid_len = 8 totres_len = 10 else: - at_fmt = self.fmt['ATOM'] + at_fmt = self.fmt["ATOM"] serial_len = 5 resid_len = 4 totres_len = 5 @@ -223,11 +240,11 @@ def write(self, selection, frame=None): attrs = {} missing_topology = [] for attr, default in ( - ('resnames', itertools.cycle(('UNK',))), - # Resids *must* be an array because we index it later - ('resids', np.ones(n_atoms, dtype=int)), - ('names', itertools.cycle(('X',))), - ('tempfactors', itertools.cycle((0.0,))), + ("resnames", itertools.cycle(("UNK",))), + # Resids *must* be an array because we index it later + ("resids", np.ones(n_atoms, dtype=int)), + ("names", itertools.cycle(("X",))), + ("tempfactors", itertools.cycle((0.0,))), ): try: attrs[attr] = getattr(atoms, attr) @@ -236,40 +253,50 @@ def write(self, selection, frame=None): missing_topology.append(attr) # ChainIDs - Try ChainIDs first, fall back to Segids try: - attrs['chainIDs'] = atoms.chainIDs + attrs["chainIDs"] = atoms.chainIDs except (NoDataError, AttributeError): # try looking for segids instead try: - attrs['chainIDs'] = atoms.segids + attrs["chainIDs"] = atoms.segids except (NoDataError, AttributeError): - attrs['chainIDs'] = itertools.cycle(('',)) + attrs["chainIDs"] = itertools.cycle(("",)) missing_topology.append(attr) if missing_topology: warnings.warn( "Supplied AtomGroup was missing the following attributes: " "{miss}. These will be written with default values. " - "".format(miss=', '.join(missing_topology))) + "".format(miss=", ".join(missing_topology)) + ) - with util.openany(self.filename, 'wt') as crd: + with util.openany(self.filename, "wt") as crd: # Write Title - crd.write(self.fmt['TITLE'].format( - frame=frame, where=u.trajectory.filename)) + crd.write( + self.fmt["TITLE"].format( + frame=frame, where=u.trajectory.filename + ) + ) crd.write("*\n") # Write NUMATOMS if self.extended or n_atoms > 99999: - crd.write(self.fmt['NUMATOMS_EXT'].format(n_atoms)) + crd.write(self.fmt["NUMATOMS_EXT"].format(n_atoms)) else: - crd.write(self.fmt['NUMATOMS'].format(n_atoms)) + crd.write(self.fmt["NUMATOMS"].format(n_atoms)) # Write all atoms current_resid = 1 - resids = attrs['resids'] + resids = attrs["resids"] for i, pos, resname, name, chainID, resid, tempfactor in zip( - range(n_atoms), coor, attrs['resnames'], attrs['names'], - attrs['chainIDs'], attrs['resids'], attrs['tempfactors']): - if not i == 0 and resids[i] != resids[i-1]: + range(n_atoms), + coor, + attrs["resnames"], + attrs["names"], + attrs["chainIDs"], + attrs["resids"], + attrs["tempfactors"], + ): + if not i == 0 and resids[i] != resids[i - 1]: current_resid += 1 # Truncate numbers @@ -277,7 +304,15 @@ def write(self, selection, frame=None): resid = util.ltruncate_int(resid, resid_len) current_resid = util.ltruncate_int(current_resid, totres_len) - crd.write(at_fmt.format( - serial=serial, totRes=current_resid, resname=resname, - name=name, pos=pos, chainID=chainID, - resSeq=resid, tempfactor=tempfactor)) + crd.write( + at_fmt.format( + serial=serial, + totRes=current_resid, + resname=resname, + name=name, + pos=pos, + chainID=chainID, + resSeq=resid, + tempfactor=tempfactor, + ) + ) diff --git a/package/MDAnalysis/coordinates/DMS.py b/package/MDAnalysis/coordinates/DMS.py index 1d207ca2bd..04367f438d 100644 --- a/package/MDAnalysis/coordinates/DMS.py +++ b/package/MDAnalysis/coordinates/DMS.py @@ -1,5 +1,5 @@ # -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*- -# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 # # MDAnalysis --- https://www.mdanalysis.org # Copyright (c) 2006-2017 The MDAnalysis Development Team and contributors @@ -46,29 +46,30 @@ class DMSReader(base.SingleFrameReaderBase): .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based """ - format = 'DMS' - units = {'time': None, 'length': 'A', 'velocity': 'A/ps'} + + format = "DMS" + units = {"time": None, "length": "A", "velocity": "A/ps"} def get_coordinates(self, cur): - cur.execute('SELECT * FROM particle') + cur.execute("SELECT * FROM particle") particles = cur.fetchall() - return [(p['x'], p['y'], p['z']) for p in particles] + return [(p["x"], p["y"], p["z"]) for p in particles] def get_particle_by_columns(self, cur, columns=None): if columns is None: - columns = ['x', 'y', 'z'] - cur.execute('SELECT * FROM particle') + columns = ["x", "y", "z"] + cur.execute("SELECT * FROM particle") particles = cur.fetchall() return [tuple([p[c] for c in columns]) for p in particles] def get_global_cell(self, cur): - cur.execute('SELECT * FROM global_cell') + cur.execute("SELECT * FROM global_cell") rows = cur.fetchall() assert len(rows) == 3 x = [row["x"] for row in rows] y = [row["y"] for row in rows] z = [row["z"] for row in rows] - return {'x': x, 'y': y, 'z': z} + return {"x": x, "y": y, "z": z} def _read_first_frame(self): coords_list = None @@ -85,7 +86,9 @@ def dict_factory(cursor, row): con.row_factory = dict_factory cur = con.cursor() coords_list = self.get_coordinates(cur) - velocities_list = self.get_particle_by_columns(cur, columns=['vx', 'vy', 'vz']) + velocities_list = self.get_particle_by_columns( + cur, columns=["vx", "vy", "vz"] + ) unitcell = self.get_global_cell(cur) if not coords_list: @@ -99,15 +102,20 @@ def dict_factory(cursor, row): self.ts = self._Timestep.from_coordinates( np.array(coords_list, dtype=np.float32), velocities=velocities, - **self._ts_kwargs) + **self._ts_kwargs, + ) 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 193d570560..3aff6d97f5 100644 --- a/package/MDAnalysis/coordinates/FHIAIMS.py +++ b/package/MDAnalysis/coordinates/FHIAIMS.py @@ -119,31 +119,35 @@ class FHIAIMSReader(base.SingleFrameReaderBase): """Reader for the FHIAIMS geometry format. - Single frame reader for the `FHI-AIMS`_ input file format. Reads - geometry (3D and molecules only), positions (absolut or fractional), - velocities if given, all according to the `FHI-AIMS format`_ - specifications + Single frame reader for the `FHI-AIMS`_ input file format. Reads + geometry (3D and molecules only), positions (absolut or fractional), + velocities if given, all according to the `FHI-AIMS format`_ + specifications """ - format = ['IN', 'FHIAIMS'] - units = {'time': 'ps', 'length': 'Angstrom', 'velocity': 'Angstrom/ps'} + + format = ["IN", "FHIAIMS"] + units = {"time": "ps", "length": "Angstrom", "velocity": "Angstrom/ps"} def _read_first_frame(self): - with util.openany(self.filename, 'rt') as fhiaimsfile: + with util.openany(self.filename, "rt") as fhiaimsfile: relative, positions, velocities, lattice_vectors = [], [], [], [] skip_tags = ["#", "initial_moment"] - oldline = '' + oldline = "" for line in fhiaimsfile: line = line.strip() if line.startswith("atom"): positions.append(line.split()[1:-1]) - relative.append('atom_frac' in line) + relative.append("atom_frac" in line) oldline = line continue if line.startswith("velocity"): - if not 'atom' in oldline: + if not "atom" in oldline: raise ValueError( - 'Non-conforming line (velocity must follow atom): ({0})in FHI-AIMS input file {0}'.format(line, self.filename)) + "Non-conforming line (velocity must follow atom): ({0})in FHI-AIMS input file {0}".format( + line, self.filename + ) + ) velocities.append(line.split()[1:]) oldline = line continue @@ -155,7 +159,10 @@ def _read_first_frame(self): oldline = line continue raise ValueError( - 'Non-conforming line: ({0})in FHI-AIMS input file {0}'.format(line, self.filename)) + "Non-conforming line: ({0})in FHI-AIMS input file {0}".format( + line, self.filename + ) + ) # positions and velocities are lists of lists of strings; they will be # cast to np.arrays(..., dtype=float32) during assignment to ts.positions/ts.velocities @@ -163,14 +170,18 @@ def _read_first_frame(self): if len(velocities) not in (0, len(positions)): raise ValueError( - 'Found incorrect number of velocity tags ({0}) in the FHI-AIMS file, should be {1}.'.format( - len(velocities), len(positions))) + "Found incorrect number of velocity tags ({0}) in the FHI-AIMS file, should be {1}.".format( + len(velocities), len(positions) + ) + ) if len(lattice_vectors) not in (0, 3): raise ValueError( - 'Found partial periodicity in FHI-AIMS file. This cannot be handled by MDAnalysis.') + "Found partial periodicity in FHI-AIMS file. This cannot be handled by MDAnalysis." + ) if len(lattice_vectors) == 0 and any(relative): raise ValueError( - 'Found relative coordinates in FHI-AIMS file without lattice info.') + "Found relative coordinates in FHI-AIMS file without lattice info." + ) # create Timestep @@ -180,7 +191,9 @@ 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 @@ -208,24 +221,24 @@ def Writer(self, filename, n_atoms=None, **kwargs): class FHIAIMSWriter(base.WriterBase): """FHI-AIMS Writer. - Single frame writer for the `FHI-AIMS`_ format. Writes geometry (3D and - molecules only), positions (absolut only), velocities if given, all - according to the `FHI-AIMS format`_ specifications. + Single frame writer for the `FHI-AIMS`_ format. Writes geometry (3D and + molecules only), positions (absolut only), velocities if given, all + according to the `FHI-AIMS format`_ specifications. - If no atom names are given, it will set each atom name to "X". + If no atom names are given, it will set each atom name to "X". """ - format = ['IN', 'FHIAIMS'] - units = {'time': None, 'length': 'Angstrom', 'velocity': 'Angstrom/ps'} + format = ["IN", "FHIAIMS"] + units = {"time": None, "length": "Angstrom", "velocity": "Angstrom/ps"} #: format strings for the FHI-AIMS file (all include newline) fmt = { # coordinates output format, see https://doi.org/10.6084/m9.figshare.12413477.v1 - 'xyz': "atom {pos[0]:12.8f} {pos[1]:12.8f} {pos[2]:12.8f} {name:<3s}\n", - 'vel': "velocity {vel[0]:12.8f} {vel[1]:12.8f} {vel[2]:12.8f}\n", + "xyz": "atom {pos[0]:12.8f} {pos[1]:12.8f} {pos[2]:12.8f} {name:<3s}\n", + "vel": "velocity {vel[0]:12.8f} {vel[1]:12.8f} {vel[2]:12.8f}\n", # unitcell - 'box_triclinic': "lattice_vector {box[0]:12.8f} {box[1]:12.8f} {box[2]:12.8f}\nlattice_vector {box[3]:12.8f} {box[4]:12.8f} {box[5]:12.8f}\nlattice_vector {box[6]:12.8f} {box[7]:12.8f} {box[8]:12.8f}\n" + "box_triclinic": "lattice_vector {box[0]:12.8f} {box[1]:12.8f} {box[2]:12.8f}\nlattice_vector {box[3]:12.8f} {box[4]:12.8f} {box[5]:12.8f}\nlattice_vector {box[6]:12.8f} {box[7]:12.8f} {box[8]:12.8f}\n", } def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): @@ -239,7 +252,7 @@ def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): number of atoms """ - self.filename = util.filename(filename, ext='.in', keep=True) + self.filename = util.filename(filename, ext=".in", keep=True) self.n_atoms = n_atoms def _write_next_frame(self, obj): @@ -268,20 +281,21 @@ def _write_next_frame(self, obj): try: names = ag.names except (AttributeError, NoDataError): - names = itertools.cycle(('X',)) - missing_topology.append('names') + names = itertools.cycle(("X",)) + missing_topology.append("names") try: atom_indices = ag.ids except (AttributeError, NoDataError): - atom_indices = range(1, ag.n_atoms+1) - missing_topology.append('ids') + atom_indices = range(1, ag.n_atoms + 1) + missing_topology.append("ids") if missing_topology: warnings.warn( "Supplied AtomGroup was missing the following attributes: " "{miss}. These will be written with default values. " - "".format(miss=', '.join(missing_topology))) + "".format(miss=", ".join(missing_topology)) + ) positions = ag.positions try: @@ -290,7 +304,7 @@ def _write_next_frame(self, obj): except (AttributeError, NoDataError): has_velocities = False - with util.openany(self.filename, 'wt') as output_fhiaims: + with util.openany(self.filename, "wt") as output_fhiaims: # Lattice try: # for AtomGroup/Universe tri_dims = obj.universe.trajectory.ts.triclinic_dimensions @@ -299,16 +313,19 @@ def _write_next_frame(self, obj): # full output if tri_dims is not None: output_fhiaims.write( - self.fmt['box_triclinic'].format(box=tri_dims.flatten())) + self.fmt["box_triclinic"].format(box=tri_dims.flatten()) + ) # Atom descriptions and coords # Dont use enumerate here, # 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)) + for atom_index, name in zip(range(ag.n_atoms), names): + output_fhiaims.write( + self.fmt["xyz"].format( + pos=positions[atom_index], name=name + ) + ) if has_velocities: - output_fhiaims.write(self.fmt['vel'].format( - vel=velocities[atom_index])) + output_fhiaims.write( + self.fmt["vel"].format(vel=velocities[atom_index]) + ) diff --git a/package/MDAnalysis/coordinates/GRO.py b/package/MDAnalysis/coordinates/GRO.py index 721fbe096f..4c17caaf5c 100644 --- a/package/MDAnalysis/coordinates/GRO.py +++ b/package/MDAnalysis/coordinates/GRO.py @@ -137,6 +137,7 @@ _TS_ORDER_Y = [5, 1, 6] _TS_ORDER_Z = [7, 8, 2] + def _gmx_to_dimensions(box): # convert gromacs ordered box to [lx, ly, lz, alpha, beta, gamma] form x = box[_TS_ORDER_X] @@ -165,12 +166,13 @@ class GROReader(base.SingleFrameReaderBase): being without dimension information (i.e. will the timestep dimension to ``None``). """ - format = 'GRO' - units = {'time': None, 'length': 'nm', 'velocity': 'nm/ps'} + + format = "GRO" + units = {"time": None, "length": "nm", "velocity": "nm/ps"} _Timestep = Timestep def _read_first_frame(self): - with util.openany(self.filename, 'rt') as grofile: + with util.openany(self.filename, "rt") as grofile: # Read first two lines to get number of atoms grofile.readline() self.n_atoms = n_atoms = int(grofile.readline()) @@ -182,12 +184,16 @@ def _read_first_frame(self): # and the third line to get the spacing between coords (cs) # (dependent upon the GRO file precision) 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)] + cs = first_atomline[25:].find(".") + 1 + ts._pos[0] = [ + 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)] + velocities[0] = [ + first_atomline[20 + cs * i : 20 + cs * (i + 1)] + for i in range(3, 6) + ] except ValueError: # Remember that we got this error missed_vel = True @@ -200,12 +206,19 @@ 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)] + velocities[pos] = [ + line[20 + cs * i : 20 + cs * (i + 1)] + for i in range(3, 6) + ] except ValueError: # Remember that we got this error missed_vel = True @@ -213,8 +226,10 @@ def _read_first_frame(self): if np.any(velocities): ts.velocities = velocities if missed_vel: - warnings.warn("Not all velocities were present. " - "Unset velocities set to zero.") + warnings.warn( + "Not all velocities were present. " + "Unset velocities set to zero." + ) self.ts.frame = 0 # 0-based frame number @@ -222,13 +237,15 @@ def _read_first_frame(self): # special case: a b c --> (a 0 0) (b 0 0) (c 0 0) # see docstring above for format (!) # Treat empty 3 entry boxes as not having a unit cell - if np.allclose(unitcell, [0., 0., 0.]): - wmsg = ("Empty box [0., 0., 0.] found - treating as missing " - "unit cell. Dimensions set to `None`.") + if np.allclose(unitcell, [0.0, 0.0, 0.0]): + wmsg = ( + "Empty box [0., 0., 0.] found - treating as missing " + "unit cell. Dimensions set to `None`." + ) warnings.warn(wmsg) self.ts.dimensions = None else: - self.ts.dimensions = np.r_[unitcell, [90., 90., 90.]] + self.ts.dimensions = np.r_[unitcell, [90.0, 90.0, 90.0]] elif len(unitcell) == 9: self.ts.dimensions = _gmx_to_dimensions(unitcell) else: # raise an error for wrong format @@ -238,7 +255,9 @@ 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) @@ -295,21 +314,23 @@ class GROWriter(base.WriterBase): information (i.e. set to ``None``). """ - format = 'GRO' - units = {'time': None, 'length': 'nm', 'velocity': 'nm/ps'} - gro_coor_limits = {'min': -999.9995, 'max': 9999.9995} + format = "GRO" + units = {"time": None, "length": "nm", "velocity": "nm/ps"} + gro_coor_limits = {"min": -999.9995, "max": 9999.9995} #: format strings for the GRO file (all include newline); precision #: of 3 decimal places is hard-coded here. fmt = { - 'n_atoms': "{0:5d}\n", # number of atoms + "n_atoms": "{0:5d}\n", # number of atoms # coordinates output format, see http://chembytes.wikidot.com/g-grofile - 'xyz': "{resid:>5d}{resname:<5.5s}{name:>5.5s}{index:>5d}{pos[0]:8.3f}{pos[1]:8.3f}{pos[2]:8.3f}\n", + "xyz": "{resid:>5d}{resname:<5.5s}{name:>5.5s}{index:>5d}{pos[0]:8.3f}{pos[1]:8.3f}{pos[2]:8.3f}\n", # unitcell - '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" + "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. @@ -344,11 +365,13 @@ def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): w.write(u.atoms) """ - self.filename = util.filename(filename, ext='gro', keep=True) + self.filename = util.filename(filename, ext="gro", keep=True) self.n_atoms = n_atoms - self.reindex = kwargs.pop('reindex', True) + 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. @@ -396,25 +419,25 @@ def write(self, obj): try: names = ag.names except (AttributeError, NoDataError): - names = itertools.cycle(('X',)) - missing_topology.append('names') + names = itertools.cycle(("X",)) + missing_topology.append("names") try: resnames = ag.resnames except (AttributeError, NoDataError): - resnames = itertools.cycle(('UNK',)) - missing_topology.append('resnames') + resnames = itertools.cycle(("UNK",)) + missing_topology.append("resnames") try: resids = ag.resids except (AttributeError, NoDataError): resids = itertools.cycle((1,)) - missing_topology.append('resids') + missing_topology.append("resids") if not self.reindex: try: atom_indices = ag.ids except (AttributeError, NoDataError): - atom_indices = range(1, ag.n_atoms+1) - missing_topology.append('ids') + atom_indices = range(1, ag.n_atoms + 1) + missing_topology.append("ids") else: atom_indices = range(1, ag.n_atoms + 1) if missing_topology: @@ -422,7 +445,8 @@ def write(self, obj): "Supplied AtomGroup was missing the following attributes: " "{miss}. These will be written with default values. " "Alternatively these can be supplied as keyword arguments." - "".format(miss=', '.join(missing_topology))) + "".format(miss=", ".join(missing_topology)) + ) positions = ag.positions @@ -431,65 +455,81 @@ def write(self, obj): # Not inplace because AtomGroup is not a copy positions = self.convert_pos_to_native(positions, inplace=False) if has_velocities: - velocities = self.convert_velocities_to_native(velocities, inplace=False) + velocities = self.convert_velocities_to_native( + velocities, inplace=False + ) # check if any coordinates are illegal # (checks the coordinates in native nm!) if not self.has_valid_coordinates(self.gro_coor_limits, positions): - 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"])) + 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"] + ) + ) - with util.openany(self.filename, 'wt') as output_gro: + with util.openany(self.filename, "wt") as output_gro: # Header - output_gro.write('Written by MDAnalysis\n') - output_gro.write(self.fmt['n_atoms'].format(ag.n_atoms)) + output_gro.write("Written by MDAnalysis\n") + output_gro.write(self.fmt["n_atoms"].format(ag.n_atoms)) # Atom descriptions and coords # Dont use enumerate here, # all attributes could be infinite cycles! 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) + range(ag.n_atoms), resids, resnames, names + ): + truncated_atom_index = util.ltruncate_int( + atom_indices[atom_index], 5 + ) truncated_resid = util.ltruncate_int(resid, 5) if has_velocities: - output_gro.write(self.fmt['xyz_v'].format( - resid=truncated_resid, - resname=resname, - index=truncated_atom_index, - name=name, - pos=positions[atom_index], - vel=velocities[atom_index], - )) + output_gro.write( + self.fmt["xyz_v"].format( + resid=truncated_resid, + resname=resname, + index=truncated_atom_index, + name=name, + pos=positions[atom_index], + vel=velocities[atom_index], + ) + ) else: - output_gro.write(self.fmt['xyz'].format( - resid=truncated_resid, - resname=resname, - index=truncated_atom_index, - name=name, - pos=positions[atom_index] - )) + output_gro.write( + self.fmt["xyz"].format( + resid=truncated_resid, + resname=resname, + index=truncated_atom_index, + name=name, + pos=positions[atom_index], + ) + ) # Footer: box dimensions - if (ag.dimensions is None or - np.allclose(ag.dimensions[3:], [90., 90., 90.])): + if ag.dimensions is None or np.allclose( + ag.dimensions[3:], [90.0, 90.0, 90.0] + ): if ag.dimensions is None: - wmsg = ("missing dimension - setting unit cell to zeroed " - "box [0., 0., 0.]") + wmsg = ( + "missing dimension - setting unit cell to zeroed " + "box [0., 0., 0.]" + ) warnings.warn(wmsg) box = np.zeros(3) else: box = self.convert_pos_to_native( - ag.dimensions[:3], inplace=False) + ag.dimensions[:3], inplace=False + ) # orthorhombic cell, only lengths along axes needed in gro - output_gro.write(self.fmt['box_orthorhombic'].format( - box=box) - ) + output_gro.write(self.fmt["box_orthorhombic"].format(box=box)) else: try: # for AtomGroup/Universe tri_dims = obj.universe.coord.triclinic_dimensions except AttributeError: # for Timestep tri_dims = obj.triclinic_dimensions # full output - box = self.convert_pos_to_native(tri_dims.flatten(), inplace=False) - output_gro.write(self.fmt['box_triclinic'].format(box=box)) + 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 f08a387221..bacd0441c3 100644 --- a/package/MDAnalysis/coordinates/GSD.py +++ b/package/MDAnalysis/coordinates/GSD.py @@ -51,6 +51,7 @@ """ import numpy as np + try: import gsd import gsd.fl @@ -72,11 +73,10 @@ class MockHOOMDTrajectory: class GSDReader(base.ReaderBase): - """Reader for the GSD format. + """Reader for the GSD format.""" - """ - format = 'GSD' - units = {'time': None, 'length': None} + format = "GSD" + units = {"time": None, "length": None} @store_init_arguments def __init__(self, filename, **kwargs): @@ -111,7 +111,7 @@ def __init__(self, filename, **kwargs): def open_trajectory(self): """opens the trajectory file using gsd.hoomd module""" self._frame = -1 - self._file = gsd_pickle_open(self.filename, mode='r') + self._file = gsd_pickle_open(self.filename, mode="r") def close(self): """close reader""" @@ -138,7 +138,7 @@ def _read_frame(self, frame): # sets the Timestep object self.ts.frame = frame - self.ts.data['step'] = myframe.configuration.step + self.ts.data["step"] = myframe.configuration.step # set frame box dimensions self.ts.dimensions = myframe.configuration.box @@ -148,9 +148,11 @@ def _read_frame(self, frame): frame_positions = myframe.particles.position n_atoms_now = frame_positions.shape[0] if n_atoms_now != self.n_atoms: - raise ValueError("Frame %d has %d atoms but the initial frame has %d" + raise ValueError( + "Frame %d has %d atoms but the initial frame has %d" " atoms. MDAnalysis in unable to deal with variable" - " topology!"%(frame, n_atoms_now, self.n_atoms)) + " topology!" % (frame, n_atoms_now, self.n_atoms) + ) else: self.ts.positions = frame_positions return self.ts @@ -206,21 +208,24 @@ class GSDPicklable(gsd.hoomd.HOOMDTrajectory): .. versionadded:: 2.0.0 """ + def __getstate__(self): return self.file.name, self.file.mode def __setstate__(self, args): gsd_version = gsd.version.version schema_version = [1, 4] - gsdfileobj = gsd.fl.open(name=args[0], - mode=args[1], - application='gsd.hoomd ' + gsd_version, - schema='hoomd', - schema_version=schema_version) + gsdfileobj = gsd.fl.open( + name=args[0], + mode=args[1], + application="gsd.hoomd " + gsd_version, + schema="hoomd", + schema_version=schema_version, + ) self.__init__(gsdfileobj) -def gsd_pickle_open(name: str, mode: str='r'): +def gsd_pickle_open(name: str, mode: str = "r"): """Open hoomd schema GSD file with pickle function implemented. This function returns a GSDPicklable object. It can be used as a @@ -278,12 +283,13 @@ def gsd_pickle_open(name: str, mode: str='r'): """ gsd_version = gsd.version.version schema_version = [1, 4] - if mode != 'r': - raise ValueError("Only read mode 'r' " - "files can be pickled.") - gsdfileobj = gsd.fl.open(name=name, - mode=mode, - application='gsd.hoomd ' + gsd_version, - schema='hoomd', - schema_version=schema_version) + if mode != "r": + raise ValueError("Only read mode 'r' " "files can be pickled.") + gsdfileobj = gsd.fl.open( + name=name, + mode=mode, + application="gsd.hoomd " + gsd_version, + schema="hoomd", + schema_version=schema_version, + ) return GSDPicklable(gsdfileobj) diff --git a/package/MDAnalysis/coordinates/INPCRD.py b/package/MDAnalysis/coordinates/INPCRD.py index 9b90f6301e..de464da089 100644 --- a/package/MDAnalysis/coordinates/INPCRD.py +++ b/package/MDAnalysis/coordinates/INPCRD.py @@ -40,15 +40,16 @@ from . import base + class INPReader(base.SingleFrameReaderBase): """Reader for Amber restart files.""" - format = ['INPCRD', 'RESTRT'] - units = {'length': 'Angstrom'} + format = ["INPCRD", "RESTRT"] + units = {"length": "Angstrom"} def _read_first_frame(self): # Read header - with open(self.filename, 'r') as inf: + with open(self.filename, "r") as inf: self.title = inf.readline().strip() line = inf.readline().split() self.n_atoms = int(line[0]) @@ -65,18 +66,26 @@ def _read_first_frame(self): for p in range(self.n_atoms // 2): line = inf.readline() # each float is f12.7, 6 floats a line - for i, dest in enumerate([(2*p, 0), (2*p, 1), (2*p, 2), - (2*p + 1, 0), (2*p + 1, 1), (2*p + 1, 2)]): - self.ts._pos[dest] = float(line[i*12:(i+1)*12]) + for i, dest in enumerate( + [ + (2 * p, 0), + (2 * p, 1), + (2 * p, 2), + (2 * p + 1, 0), + (2 * p + 1, 1), + (2 * p + 1, 2), + ] + ): + self.ts._pos[dest] = float(line[i * 12 : (i + 1) * 12]) # Read last coordinate if necessary if self.n_atoms % 2: line = inf.readline() for i in range(3): - self.ts._pos[-1, i] = float(line[i*12:(i+1)*12]) + self.ts._pos[-1, i] = float(line[i * 12 : (i + 1) * 12]) @staticmethod def parse_n_atoms(filename, **kwargs): - with open(filename, 'r') as f: + with open(filename, "r") as f: f.readline() n_atoms = int(f.readline().split()[0]) return n_atoms diff --git a/package/MDAnalysis/coordinates/LAMMPS.py b/package/MDAnalysis/coordinates/LAMMPS.py index 2a91c44e33..c45345c607 100644 --- a/package/MDAnalysis/coordinates/LAMMPS.py +++ b/package/MDAnalysis/coordinates/LAMMPS.py @@ -148,8 +148,13 @@ from . import base import warnings -btype_sections = {'bond':'Bonds', 'angle':'Angles', - 'dihedral':'Dihedrals', 'improper':'Impropers'} +btype_sections = { + "bond": "Bonds", + "angle": "Angles", + "dihedral": "Dihedrals", + "improper": "Impropers", +} + class DCDWriter(DCD.DCDWriter): """Write a LAMMPS_ DCD trajectory. @@ -159,18 +164,26 @@ class DCDWriter(DCD.DCDWriter): "Angstrom". See :mod:`MDAnalysis.units` for other recognized values. """ - format = 'LAMMPS' + + format = "LAMMPS" multiframe = True - flavor = 'LAMMPS' + flavor = "LAMMPS" def __init__(self, *args, **kwargs): - self.units = {'time': 'fs', 'length': 'Angstrom'} # must be instance level - self.units['time'] = kwargs.pop('timeunit', self.units['time']) - self.units['length'] = kwargs.pop('lengthunit', self.units['length']) + self.units = { + "time": "fs", + "length": "Angstrom", + } # must be instance level + self.units["time"] = kwargs.pop("timeunit", self.units["time"]) + self.units["length"] = kwargs.pop("lengthunit", self.units["length"]) for unit_type, unit in self.units.items(): try: if units.unit_types[unit] != unit_type: - raise TypeError("LAMMPS DCDWriter: wrong unit {0!r} for unit type {1!r}".format(unit, unit_type)) + raise TypeError( + "LAMMPS DCDWriter: wrong unit {0!r} for unit type {1!r}".format( + unit, unit_type + ) + ) except KeyError: errmsg = f"LAMMPS DCDWriter: unknown unit {unit}" raise ValueError(errmsg) from None @@ -187,20 +200,30 @@ class DCDReader(DCD.DCDReader): .. _units style: http://lammps.sandia.gov/doc/units.html """ - format = 'LAMMPS' - flavor = 'LAMMPS' + + format = "LAMMPS" + flavor = "LAMMPS" @store_init_arguments def __init__(self, dcdfilename, **kwargs): - self.units = {'time': 'fs', 'length': 'Angstrom'} # must be instance level - self.units['time'] = kwargs.pop('timeunit', self.units['time']) - self.units['length'] = kwargs.pop('lengthunit', self.units['length']) + self.units = { + "time": "fs", + "length": "Angstrom", + } # must be instance level + self.units["time"] = kwargs.pop("timeunit", self.units["time"]) + self.units["length"] = kwargs.pop("lengthunit", self.units["length"]) for unit_type, unit in self.units.items(): try: if units.unit_types[unit] != unit_type: - raise TypeError("LAMMPS DCDReader: wrong unit {0!r} for unit type {1!r}".format(unit, unit_type)) + raise TypeError( + "LAMMPS DCDReader: wrong unit {0!r} for unit type {1!r}".format( + unit, unit_type + ) + ) except KeyError: - raise ValueError("LAMMPS DCDReader: unknown unit {0!r}".format(unit)) + raise ValueError( + "LAMMPS DCDReader: unknown unit {0!r}".format(unit) + ) super(DCDReader, self).__init__(dcdfilename, **kwargs) @@ -211,30 +234,35 @@ class DATAReader(base.SingleFrameReaderBase): .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based """ - format = 'DATA' - units = {'time': None, 'length': 'Angstrom', 'velocity': 'Angstrom/fs'} + + format = "DATA" + units = {"time": None, "length": "Angstrom", "velocity": "Angstrom/fs"} @store_init_arguments def __init__(self, filename, **kwargs): - self.n_atoms = kwargs.pop('n_atoms', None) + self.n_atoms = kwargs.pop("n_atoms", None) if self.n_atoms is None: # this should be done by parsing DATA first raise ValueError("DATAReader requires n_atoms keyword") - self.atom_style = kwargs.pop('atom_style', None) + self.atom_style = kwargs.pop("atom_style", None) super(DATAReader, self).__init__(filename, **kwargs) def _read_first_frame(self): with DATAParser(self.filename) as p: - self.ts = p.read_DATA_timestep(self.n_atoms, self._Timestep, - self._ts_kwargs, self.atom_style) + self.ts = p.read_DATA_timestep( + self.n_atoms, self._Timestep, self._ts_kwargs, self.atom_style + ) self.ts.frame = 0 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 + class DATAWriter(base.WriterBase): """Write out the current time step as a LAMMPS DATA file. @@ -263,7 +291,8 @@ class DATAWriter(base.WriterBase): an integer >= 1. """ - format = 'DATA' + + format = "DATA" def __init__(self, filename, convert_units=True, **kwargs): """Set up a DATAWriter @@ -275,20 +304,21 @@ def __init__(self, filename, convert_units=True, **kwargs): convert_units : bool, optional units are converted to the MDAnalysis base format; [``True``] """ - self.filename = util.filename(filename, ext='data', keep=True) + self.filename = util.filename(filename, ext="data", keep=True) self.convert_units = convert_units - self.units = {'time': 'fs', 'length': 'Angstrom'} - self.units['length'] = kwargs.pop('lengthunit', self.units['length']) - self.units['time'] = kwargs.pop('timeunit', self.units['time']) - self.units['velocity'] = kwargs.pop('velocityunit', - self.units['length']+'/'+self.units['time']) + self.units = {"time": "fs", "length": "Angstrom"} + self.units["length"] = kwargs.pop("lengthunit", self.units["length"]) + self.units["time"] = kwargs.pop("timeunit", self.units["time"]) + self.units["velocity"] = kwargs.pop( + "velocityunit", self.units["length"] + "/" + self.units["time"] + ) def _write_atoms(self, atoms, data): - self.f.write('\n') - self.f.write('Atoms\n') - self.f.write('\n') + self.f.write("\n") + self.f.write("Atoms\n") + self.f.write("\n") try: charges = atoms.charges @@ -303,63 +333,84 @@ 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(indices, moltags, - types, charges, coordinates): + for index, moltag, atype, charge, coords in zip( + indices, moltags, types, charges, coordinates + ): x, y, z = coords - self.f.write(f"{index:d} {moltag:d} {atype:d} {charge:f}" - f" {x:f} {y:f} {z:f}\n") + self.f.write( + f"{index:d} {moltag:d} {atype:d} {charge:f}" + f" {x:f} {y:f} {z:f}\n" + ) else: - for index, moltag, atype, coords in zip(indices, moltags, types, - coordinates): + for index, moltag, atype, coords in zip( + indices, moltags, types, coordinates + ): x, y, z = coords - self.f.write(f"{index:d} {moltag:d} {atype:d}" - f" {x:f} {y:f} {z:f}\n") + self.f.write( + f"{index:d} {moltag:d} {atype:d}" f" {x:f} {y:f} {z:f}\n" + ) def _write_velocities(self, atoms): - self.f.write('\n') - self.f.write('Velocities\n') - self.f.write('\n') + self.f.write("\n") + 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:f} {y:f} {z:f}\n'.format(i=index, x=vel[0], - y=vel[1], z=vel[2])) + self.f.write( + "{i:d} {x:f} {y:f} {z:f}\n".format( + i=index, x=vel[0], y=vel[1], z=vel[2] + ) + ) def _write_masses(self, atoms): - self.f.write('\n') - self.f.write('Masses\n') - self.f.write('\n') + self.f.write("\n") + self.f.write("Masses\n") + self.f.write("\n") mass_dict = {} max_type = max(atoms.types.astype(np.int32)) - for atype in range(1, max_type+1): + 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) + masses = set( + atoms.universe.atoms.select_atoms( + "type {:d}".format(atype) + ).masses + ) if len(masses) == 0: mass_dict[atype] = 1.0 else: mass_dict[atype] = masses.pop() if masses: - raise ValueError('LAMMPS DATAWriter: to write data file, '+ - 'atoms with same type must have same mass') + raise ValueError( + "LAMMPS DATAWriter: to write data file, " + + "atoms with same type must have same mass" + ) for atype, mass in mass_dict.items(): - self.f.write('{:d} {:f}\n'.format(atype, mass)) + self.f.write("{:d} {:f}\n".format(atype, mass)) def _write_bonds(self, bonds): - self.f.write('\n') - self.f.write('{}\n'.format(btype_sections[bonds.btype])) - self.f.write('\n') - for bond, i in zip(bonds, range(1, len(bonds)+1)): + self.f.write("\n") + self.f.write("{}\n".format(btype_sections[bonds.btype])) + self.f.write("\n") + for bond, i in zip(bonds, range(1, len(bonds) + 1)): try: - self.f.write('{:d} {:d} '.format(i, int(bond.type))+\ - ' '.join((bond.atoms.indices + 1).astype(str))+'\n') + self.f.write( + "{:d} {:d} ".format(i, int(bond.type)) + + " ".join((bond.atoms.indices + 1).astype(str)) + + "\n" + ) except TypeError: - errmsg = (f"LAMMPS DATAWriter: Trying to write bond, but bond " - f"type {bond.type} is not numerical.") + errmsg = ( + f"LAMMPS DATAWriter: Trying to write bond, but bond " + f"type {bond.type} is not numerical." + ) raise TypeError(errmsg) from None def _write_dimensions(self, dimensions): @@ -367,18 +418,22 @@ def _write_dimensions(self, dimensions): units and then write the dimensions section """ if self.convert_units: - triv = self.convert_pos_to_native(mdamath.triclinic_vectors( - dimensions),inplace=False) - self.f.write('\n') - self.f.write('{:f} {:f} xlo xhi\n'.format(0., triv[0][0])) - self.f.write('{:f} {:f} ylo yhi\n'.format(0., triv[1][1])) - self.f.write('{:f} {:f} zlo zhi\n'.format(0., triv[2][2])) + triv = self.convert_pos_to_native( + mdamath.triclinic_vectors(dimensions), inplace=False + ) + self.f.write("\n") + self.f.write("{:f} {:f} xlo xhi\n".format(0.0, triv[0][0])) + self.f.write("{:f} {:f} ylo yhi\n".format(0.0, triv[1][1])) + self.f.write("{:f} {:f} zlo zhi\n".format(0.0, triv[2][2])) if any([triv[1][0], triv[2][0], triv[2][1]]): - self.f.write('{xy:f} {xz:f} {yz:f} xy xz yz\n'.format( - xy=triv[1][0], xz=triv[2][0], yz=triv[2][1])) - self.f.write('\n') - - @requires('types', 'masses') + self.f.write( + "{xy:f} {xz:f} {yz:f} xy xz yz\n".format( + xy=triv[1][0], xz=triv[2][0], yz=triv[2][1] + ) + ) + self.f.write("\n") + + @requires("types", "masses") def write(self, selection, frame=None): """Write selection at current trajectory frame to file. @@ -419,8 +474,10 @@ 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: @@ -431,27 +488,38 @@ def write(self, selection, frame=None): has_velocities = True features = {} - with util.openany(self.filename, 'wt') as self.f: - self.f.write('LAMMPS data file via MDAnalysis\n') - self.f.write('\n') - self.f.write('{:>12d} atoms\n'.format(len(atoms))) - - attrs = [('bond', 'bonds'), ('angle', 'angles'), - ('dihedral', 'dihedrals'), ('improper', 'impropers')] + with util.openany(self.filename, "wt") as self.f: + self.f.write("LAMMPS data file via MDAnalysis\n") + self.f.write("\n") + self.f.write("{:>12d} atoms\n".format(len(atoms))) + + attrs = [ + ("bond", "bonds"), + ("angle", "angles"), + ("dihedral", "dihedrals"), + ("improper", "impropers"), + ] 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) + atoms, strict=True + ) - self.f.write('\n') - self.f.write('{:>12d} atom types\n'.format(max(atoms.types.astype(np.int32)))) + self.f.write("\n") + self.f.write( + "{:>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) @@ -467,7 +535,7 @@ def write(self, selection, frame=None): class DumpReader(base.ReaderBase): - """Reads the default `LAMMPS dump format + """Reads the default `LAMMPS dump format `__ Supports coordinates in the LAMMPS "unscaled" (x,y,z), "scaled" (xs,ys,zs), @@ -523,10 +591,10 @@ class DumpReader(base.ReaderBase): Convention used in coordinates, can be one of the following according to the `LAMMPS documentation `__: - - "auto" - Detect coordinate type from file column header. If auto + - "auto" - Detect coordinate type from file column header. If auto detection is used, the guessing checks whether the coordinates - fit each convention in the order "unscaled", "scaled", "unwrapped", - "scaled_unwrapped" and whichever set of coordinates is detected + fit each convention in the order "unscaled", "scaled", "unwrapped", + "scaled_unwrapped" and whichever set of coordinates is detected first will be used. - "scaled" - Coordinates wrapped in box and scaled by box length (see note below), i.e., xs, ys, zs @@ -536,13 +604,13 @@ class DumpReader(base.ReaderBase): - "unwrapped" - Coordinates unwrapped, i.e., xu, yu, zu If coordinates are given in the scaled coordinate convention (xs,ys,zs) - or scaled unwrapped coordinate convention (xsu,ysu,zsu) they will + or scaled unwrapped coordinate convention (xsu,ysu,zsu) they will automatically be converted from their scaled/fractional representation to their real values. unwrap_images : bool (optional) default=False - If `True` and the dump file contains image flags, the coordinates - will be unwrapped. See `read_data - `__ in the lammps + If `True` and the dump file contains image flags, the coordinates + will be unwrapped. See `read_data + `__ in the lammps documentation for more information. **kwargs Other keyword arguments used in :class:`~MDAnalysis.coordinates.base.ReaderBase` @@ -561,15 +629,21 @@ class DumpReader(base.ReaderBase): Now parses coordinates in multiple lammps conventions (x,xs,xu,xsu) .. versionadded:: 0.19.0 """ - format = 'LAMMPSDUMP' - _conventions = ["auto", "unscaled", "scaled", "unwrapped", - "scaled_unwrapped"] + + format = "LAMMPSDUMP" + _conventions = [ + "auto", + "unscaled", + "scaled", + "unwrapped", + "scaled_unwrapped", + ] _coordtype_column_names = { "unscaled": ["x", "y", "z"], "scaled": ["xs", "ys", "zs"], "unwrapped": ["xu", "yu", "zu"], - "scaled_unwrapped": ["xsu", "ysu", "zsu"] + "scaled_unwrapped": ["xsu", "ysu", "zsu"], } _parsable_columns = ["id", "vx", "vy", "vz", "fx", "fy", "fz"] @@ -577,10 +651,14 @@ class DumpReader(base.ReaderBase): _parsable_columns += _coordtype_column_names[key] @store_init_arguments - def __init__(self, filename, - lammps_coordinate_convention="auto", - unwrap_images=False, - additional_columns=None, **kwargs): + def __init__( + self, + filename, + lammps_coordinate_convention="auto", + unwrap_images=False, + additional_columns=None, + **kwargs, + ): super(DumpReader, self).__init__(filename, **kwargs) root, ext = os.path.splitext(self.filename) @@ -588,22 +666,28 @@ def __init__(self, filename, self.lammps_coordinate_convention = lammps_coordinate_convention else: option_string = "'" + "', '".join(self._conventions) + "'" - raise ValueError("lammps_coordinate_convention=" - f"'{lammps_coordinate_convention}'" - " is not a valid option. " - f"Please choose one of {option_string}") + raise ValueError( + "lammps_coordinate_convention=" + f"'{lammps_coordinate_convention}'" + " is not a valid option. " + f"Please choose one of {option_string}" + ) self._unwrap = unwrap_images - if (util.iterable(additional_columns) - or additional_columns is None - or additional_columns is True): + if ( + util.iterable(additional_columns) + or additional_columns is None + or additional_columns is True + ): self._additional_columns = additional_columns else: - raise ValueError(f"additional_columns={additional_columns} " - "is not a valid option. Please provide an " - "iterable containing the additional" - "column headers.") + raise ValueError( + f"additional_columns={additional_columns} " + "is not a valid option. Please provide an " + "iterable containing the additional" + "column headers." + ) self._cache = {} @@ -618,7 +702,7 @@ def _reopen(self): self.ts.frame = -1 @property - @cached('n_atoms') + @cached("n_atoms") def n_atoms(self): with util.anyopen(self.filename) as f: f.readline() @@ -628,7 +712,7 @@ def n_atoms(self): return n_atoms @property - @cached('n_frames') + @cached("n_frames") def n_frames(self): # 2(timestep) + 2(natoms info) + 4(box info) + 1(atom header) + n_atoms lines_per_frame = self.n_atoms + 9 @@ -645,7 +729,7 @@ def n_frames(self): return len(self._offsets) def close(self): - if hasattr(self, '_file'): + if hasattr(self, "_file"): self._file.close() def _read_frame(self, frame): @@ -663,14 +747,16 @@ def _read_next_timestep(self): f.readline() # ITEM TIMESTEP step_num = int(f.readline()) - ts.data['step'] = step_num - ts.data['time'] = step_num * ts.dt + ts.data["step"] = step_num + ts.data["time"] = step_num * ts.dt f.readline() # ITEM NUMBER OF ATOMS n_atoms = int(f.readline()) if n_atoms != self.n_atoms: - raise ValueError("Number of atoms in trajectory changed " - "this is not supported in MDAnalysis") + raise ValueError( + "Number of atoms in trajectory changed " + "this is not supported in MDAnalysis" + ) triclinic = len(f.readline().split()) == 9 # ITEM BOX BOUNDS if triclinic: @@ -698,7 +784,7 @@ def _read_next_timestep(self): xlen = xhi - xlo ylen = yhi - ylo zlen = zhi - zlo - alpha = beta = gamma = 90. + alpha = beta = gamma = 90.0 ts.dimensions = xlen, ylen, zlen, alpha, beta, gamma indices = np.zeros(self.n_atoms, dtype=int) @@ -709,8 +795,9 @@ def _read_next_timestep(self): convention_to_col_ix = {} for cv_name, cv_col_names in self._coordtype_column_names.items(): try: - convention_to_col_ix[cv_name] = [attr_to_col_ix[x] - for x in cv_col_names] + convention_to_col_ix[cv_name] = [ + attr_to_col_ix[x] for x in cv_col_names + ] except KeyError: pass @@ -718,8 +805,9 @@ def _read_next_timestep(self): try: image_cols = [attr_to_col_ix[x] for x in ["ix", "iy", "iz"]] except: - raise ValueError("Trajectory must have image flag in order " - "to unwrap.") + raise ValueError( + "Trajectory must have image flag in order " "to unwrap." + ) self._has_vels = all(x in attr_to_col_ix for x in ["vx", "vy", "vz"]) if self._has_vels: @@ -737,13 +825,17 @@ 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: - raise ValueError(f"No coordinates following convention " - "{self.lammps_coordinate_convention} found in " - "timestep") + raise ValueError( + f"No coordinates following convention " + "{self.lammps_coordinate_convention} found in " + "timestep" + ) coord_cols = convention_to_col_ix[self.lammps_coordinate_convention] if self._unwrap: @@ -759,10 +851,13 @@ def _read_next_timestep(self): additional_keys = set(attrs).difference(self._parsable_columns) elif self._additional_columns: if not all([key in attrs for key in self._additional_columns]): - warnings.warn("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] + warnings.warn( + "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 + ] else: additional_keys = [] for key in additional_keys: @@ -773,8 +868,9 @@ 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:] @@ -791,8 +887,9 @@ 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] @@ -805,11 +902,12 @@ def _read_next_timestep(self): for attribute_key in additional_keys: ts.data[attribute_key] = ts.data[attribute_key][order] - if (self.lammps_coordinate_convention.startswith("scaled")): + 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,:] + ts.positions -= np.array([xlo, ylo, zlo])[None, :] return ts diff --git a/package/MDAnalysis/coordinates/MMTF.py b/package/MDAnalysis/coordinates/MMTF.py index 00ef477437..7894e9dc4a 100644 --- a/package/MDAnalysis/coordinates/MMTF.py +++ b/package/MDAnalysis/coordinates/MMTF.py @@ -50,7 +50,7 @@ def _parse_mmtf(fn): - if fn.endswith('gz'): + if fn.endswith("gz"): return mmtf.parse_gzip(fn) else: return mmtf.parse(fn) @@ -65,17 +65,19 @@ class MMTFReader(base.SingleFrameReaderBase): Protein Data Bank. The Reader will be removed in version 3.0. Users are encouraged to instead use alternative PDB formats. """ - format = 'MMTF' + + format = "MMTF" @store_init_arguments def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): - wmsg = ("The MMTF Reader is deprecated and will be removed in " - "MDAnalysis version 3.0.0") + wmsg = ( + "The MMTF Reader is deprecated and will be removed in " + "MDAnalysis version 3.0.0" + ) warnings.warn(wmsg, DeprecationWarning) super(MMTFReader, self).__init__( - filename, convert_units, n_atoms, - **kwargs + filename, convert_units, n_atoms, **kwargs ) @staticmethod @@ -87,9 +89,9 @@ def _format_hint(thing): return isinstance(thing, mmtf.MMTFDecoder) @due.dcite( - Doi('10.1371/journal.pcbi.1005575'), + Doi("10.1371/journal.pcbi.1005575"), description="MMTF Reader", - path='MDAnalysis.coordinates.MMTF', + path="MDAnalysis.coordinates.MMTF", ) def _read_first_frame(self): # TOOD: Check units? @@ -99,8 +101,7 @@ def _read_first_frame(self): top = _parse_mmtf(self.filename) self.n_atoms = top.num_atoms - self.ts = ts = self._Timestep(self.n_atoms, - **self._ts_kwargs) + self.ts = ts = self._Timestep(self.n_atoms, **self._ts_kwargs) ts._pos[:, 0] = top.x_coord_list ts._pos[:, 1] = top.y_coord_list ts._pos[:, 2] = top.z_coord_list diff --git a/package/MDAnalysis/coordinates/NAMDBIN.py b/package/MDAnalysis/coordinates/NAMDBIN.py index b9425f18f9..834ea346ae 100644 --- a/package/MDAnalysis/coordinates/NAMDBIN.py +++ b/package/MDAnalysis/coordinates/NAMDBIN.py @@ -49,29 +49,30 @@ class NAMDBINReader(base.SingleFrameReaderBase): """Reader for NAMD binary coordinate files. - - - .. versionadded:: 1.0.0 + + + .. versionadded:: 1.0.0 """ - format = ['COOR', 'NAMDBIN'] - units = {'length': 'Angstrom'} + format = ["COOR", "NAMDBIN"] + units = {"length": "Angstrom"} def _read_first_frame(self): # Read header - with open(self.filename, 'rb') as namdbin: + with open(self.filename, "rb") as namdbin: self.n_atoms = np.fromfile(namdbin, dtype=np.int32, count=1)[0] self.ts = self._Timestep(self.n_atoms, **self._ts_kwargs) self.ts.frame = 0 - 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) + 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 + ) @staticmethod def parse_n_atoms(filename, **kwargs): - with open(filename, 'rb') as namdbin: + with open(filename, "rb") as namdbin: n_atoms = np.fromfile(namdbin, dtype=np.int32, count=1)[0] return n_atoms @@ -93,7 +94,7 @@ def Writer(self, filename, **kwargs): class NAMDBINWriter(base.WriterBase): """Writer for NAMD binary coordinate files. - + Note ---- @@ -102,8 +103,9 @@ class NAMDBINWriter(base.WriterBase): .. versionadded:: 1.0.0 """ - format = ['COOR', 'NAMDBIN'] - units = {'time': None, 'length': 'Angstrom'} + + format = ["COOR", "NAMDBIN"] + units = {"time": None, "length": "Angstrom"} def __init__(self, filename, n_atoms=None, **kwargs): """ @@ -134,16 +136,16 @@ def _write_next_frame(self, obj): Deprecated support for Timestep argument has now been removed. Use AtomGroup or Universe as an input instead. """ - if hasattr(obj, 'atoms'): # AtomGroup or Universe + if hasattr(obj, "atoms"): # AtomGroup or Universe atoms = obj.atoms n_atoms = len(atoms) - coor = atoms.positions.reshape(n_atoms*3) + coor = atoms.positions.reshape(n_atoms * 3) else: errmsg = "Input obj is neither an AtomGroup or Universe" raise TypeError(errmsg) from None - with util.openany(self.filename, 'wb') as namdbin: + with util.openany(self.filename, "wb") as namdbin: # Write NUMATOMS - namdbin.write(pack('i', n_atoms)) + namdbin.write(pack("i", n_atoms)) # Write Coordinate - namdbin.write(pack('{:d}d'.format(len(coor)), *coor)) + namdbin.write(pack("{:d}d".format(len(coor)), *coor)) diff --git a/package/MDAnalysis/coordinates/PDBQT.py b/package/MDAnalysis/coordinates/PDBQT.py index f0913d6e04..44f19e54f8 100644 --- a/package/MDAnalysis/coordinates/PDBQT.py +++ b/package/MDAnalysis/coordinates/PDBQT.py @@ -141,8 +141,9 @@ class PDBQTReader(base.SingleFrameReaderBase): .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based """ - format = 'PDBQT' - units = {'time': None, 'length': 'Angstrom'} + + format = "PDBQT" + units = {"time": None, "length": "Angstrom"} def _read_first_frame(self): coords = [] @@ -152,21 +153,23 @@ def _read_first_frame(self): # Should only break at the 'END' of a model definition # and prevent premature exit for a torsion termination # , eg, ENDBRANCH - if line.startswith('END\n'): + if line.startswith("END\n"): break - if line.startswith('CRYST1'): + 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')): + if line.startswith(("ATOM", "HETATM")): # convert all entries at the end once for optimal speed coords.append([line[30:38], line[38:46], line[46:54]]) self.n_atoms = len(coords) - self.ts = self._Timestep.from_coordinates( - coords, - **self._ts_kwargs) + self.ts = self._Timestep.from_coordinates(coords, **self._ts_kwargs) self.ts.dimensions = unitcell self.ts.frame = 0 # 0-based frame number if self.convert_units: @@ -204,23 +207,27 @@ class PDBQTWriter(base.WriterBase): """ fmt = { - 'ATOM': ("ATOM {serial:5d} {name:<4.4s} {resName:<4.4s}" - "{chainID:1.1s}{resSeq:4d}{iCode:1.1s}" - " {pos[0]:8.3f}{pos[1]:8.3f}{pos[2]:8.3f}{occupancy:6.2f}" - "{tempFactor:6.2f} {charge:< 1.3f} {element:<2.2s}\n"), - 'REMARK': "REMARK {0}\n", - 'TITLE': "TITLE {0}\n", - 'CRYST1': ("CRYST1{box[0]:9.3f}{box[1]:9.3f}{box[2]:9.3f}" - "{ang[0]:7.2f}{ang[1]:7.2f}{ang[2]:7.2f} " - "{spacegroup:<11s}{zvalue:4d}\n"), + "ATOM": ( + "ATOM {serial:5d} {name:<4.4s} {resName:<4.4s}" + "{chainID:1.1s}{resSeq:4d}{iCode:1.1s}" + " {pos[0]:8.3f}{pos[1]:8.3f}{pos[2]:8.3f}{occupancy:6.2f}" + "{tempFactor:6.2f} {charge:< 1.3f} {element:<2.2s}\n" + ), + "REMARK": "REMARK {0}\n", + "TITLE": "TITLE {0}\n", + "CRYST1": ( + "CRYST1{box[0]:9.3f}{box[1]:9.3f}{box[2]:9.3f}" + "{ang[0]:7.2f}{ang[1]:7.2f}{ang[2]:7.2f} " + "{spacegroup:<11s}{zvalue:4d}\n" + ), } - format = 'PDBQT' - units = {'time': None, 'length': 'Angstrom'} + format = "PDBQT" + units = {"time": None, "length": "Angstrom"} pdb_coor_limits = {"min": -999.9995, "max": 9999.9995} def __init__(self, filename, **kwargs): - self.filename = util.filename(filename, ext='pdbqt', keep=True) - self.pdb = util.anyopen(self.filename, 'wt') + self.filename = util.filename(filename, ext="pdbqt", keep=True) + self.pdb = util.anyopen(self.filename, "wt") def close(self): self.pdb.close() @@ -262,21 +269,23 @@ 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 = {} missing_topology = [] for attr, dflt in ( - ('altLocs', ' '), - ('charges', 0.0), - ('icodes', ' '), - ('names', 'X'), - ('occupancies', 1.0), - ('resids', 1), - ('resnames', 'UNK'), - ('tempfactors', 0.0), - ('types', ' '), + ("altLocs", " "), + ("charges", 0.0), + ("icodes", " "), + ("names", "X"), + ("occupancies", 1.0), + ("resids", 1), + ("resnames", "UNK"), + ("tempfactors", 0.0), + ("types", " "), ): try: attrs[attr] = getattr(atoms, attr) @@ -285,18 +294,19 @@ def write(self, selection, frame=None): missing_topology.append(attr) # Order of preference: chainids -> segids -> blank string try: - attrs['chainids'] = atoms.chainids + attrs["chainids"] = atoms.chainids except AttributeError: try: - attrs['chainids'] = atoms.segids + attrs["chainids"] = atoms.segids except AttributeError: - attrs['chainids'] = itertools.cycle((' ',)) - missing_topology.append('chainids') + attrs["chainids"] = itertools.cycle((" ",)) + missing_topology.append("chainids") if missing_topology: warnings.warn( "Supplied AtomGroup was missing the following attributes: " "{miss}. These will be written with default values. " - "".format(miss=', '.join(missing_topology))) + "".format(miss=", ".join(missing_topology)) + ) # check if any coordinates are illegal (coordinates are already # in Angstroem per package default) @@ -310,28 +320,53 @@ 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 # http://www.wwpdb.org/documentation/file-format-content/format32/sect2.html line = "FRAME " + str(frame) + " FROM " + str(u.trajectory.filename) - self.pdb.write(self.fmt['TITLE'].format(line)) + self.pdb.write(self.fmt["TITLE"].format(line)) # Write CRYST1 record # http://www.wwpdb.org/documentation/file-format-content/format32/sect8.html box = self.convert_dimensions_to_unitcell(u.trajectory.ts) - self.pdb.write(self.fmt['CRYST1'].format(box=box[:3], ang=box[3:], - spacegroup='P 1', zvalue=1)) + self.pdb.write( + self.fmt["CRYST1"].format( + box=box[:3], ang=box[3:], spacegroup="P 1", zvalue=1 + ) + ) # Write atom records # http://www.wwpdb.org/documentation/file-format-content/format32/sect9.html - for serial, (pos, name, resname, chainid, resid, icode, - occupancy, tempfactor, charge, element) in enumerate( - zip(coor, attrs['names'], attrs['resnames'], attrs['chainids'], - attrs['resids'], attrs['icodes'], attrs['occupancies'], - attrs['tempfactors'], attrs['charges'], attrs['types']), - start=1): + for serial, ( + pos, + name, + resname, + chainid, + resid, + icode, + occupancy, + tempfactor, + charge, + element, + ) in enumerate( + zip( + coor, + attrs["names"], + attrs["resnames"], + attrs["chainids"], + attrs["resids"], + attrs["icodes"], + attrs["occupancies"], + attrs["tempfactors"], + attrs["charges"], + attrs["types"], + ), + start=1, + ): serial = util.ltruncate_int(serial, 5) # check for overflow here? resid = util.ltruncate_int(resid, 4) name = name[:4] @@ -339,18 +374,20 @@ def write(self, selection, frame=None): name = " " + name # customary to start in column 14 chainid = chainid.strip()[-1:] # take the last character - self.pdb.write(self.fmt['ATOM'].format( - serial=serial, - name=name, - resName=resname, - chainID=chainid, - resSeq=resid, - iCode=icode, - pos=pos, - occupancy=occupancy, - tempFactor=tempfactor, - charge=charge, - element=element, - )) + self.pdb.write( + self.fmt["ATOM"].format( + serial=serial, + name=name, + resName=resname, + chainID=chainid, + resSeq=resid, + iCode=icode, + pos=pos, + occupancy=occupancy, + tempFactor=tempfactor, + charge=charge, + element=element, + ) + ) self.close() diff --git a/package/MDAnalysis/coordinates/PQR.py b/package/MDAnalysis/coordinates/PQR.py index c93d783dc6..18e1ad4369 100644 --- a/package/MDAnalysis/coordinates/PQR.py +++ b/package/MDAnalysis/coordinates/PQR.py @@ -122,24 +122,26 @@ class PQRReader(base.SingleFrameReaderBase): .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based """ - format = 'PQR' - units = {'time': None, 'length': 'Angstrom'} + + format = "PQR" + units = {"time": None, "length": "Angstrom"} # how to slice fields[x:y] to grab coordinates _SLICE_INDICES = { - 'ORIGINAL': (-5, -2), - 'NO_CHAINID': (-5, -2), - 'GROMACS': (-6, -3), + "ORIGINAL": (-5, -2), + "NO_CHAINID": (-5, -2), + "GROMACS": (-6, -3), } def _read_first_frame(self): from ..topology.PQRParser import PQRParser + flavour = None coords = [] with util.openany(self.filename) as pqrfile: for line in pqrfile: - if line.startswith(('ATOM', 'HETATM')): + if line.startswith(("ATOM", "HETATM")): if flavour is None: flavour = PQRParser.guess_flavour(line) x, y = self._SLICE_INDICES[flavour] @@ -149,8 +151,7 @@ def _read_first_frame(self): coords.append(fields[x:y]) self.n_atoms = len(coords) - self.ts = self._Timestep.from_coordinates( - coords, **self._ts_kwargs) + self.ts = self._Timestep.from_coordinates(coords, **self._ts_kwargs) self.ts.frame = 0 # 0-based frame number if self.convert_units: # in-place ! @@ -192,13 +193,16 @@ class PQRWriter(base.WriterBase): Files are now written in `wt` mode, and keep extensions, allowing for files to be written under compressed formats """ - format = 'PQR' - units = {'time': None, 'length': 'Angstrom'} + + format = "PQR" + units = {"time": None, "length": "Angstrom"} # serial, atomName, residueName, chainID, residueNumber, XYZ, charge, radius - fmt_ATOM = ("ATOM {serial:6d} {name:<4} {resname:<3} {chainid:1.1}" - " {resid:4d} {pos[0]:-8.3f} {pos[1]:-8.3f}" - " {pos[2]:-8.3f} {charge:-7.4f} {radius:6.4f}\n") + fmt_ATOM = ( + "ATOM {serial:6d} {name:<4} {resname:<3} {chainid:1.1}" + " {resid:4d} {pos[0]:-8.3f} {pos[1]:-8.3f}" + " {pos[2]:-8.3f} {charge:-7.4f} {radius:6.4f}\n" + ) fmt_remark = "REMARK {0} {1}\n" def __init__(self, filename, convert_units=True, **kwargs): @@ -214,9 +218,11 @@ def __init__(self, filename, convert_units=True, **kwargs): remark lines (list of strings) or single string to be added to the top of the PQR file """ - self.filename = util.filename(filename, ext='pqr', keep=True) - self.convert_units = convert_units # convert length and time to base units - self.remarks = kwargs.pop('remarks', "PQR file written by MDAnalysis") + self.filename = util.filename(filename, ext="pqr", keep=True) + self.convert_units = ( + convert_units # convert length and time to base units + ) + self.remarks = kwargs.pop("remarks", "PQR file written by MDAnalysis") def write(self, selection, frame=None): """Write selection at current trajectory frame to file. @@ -250,9 +256,13 @@ 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) # inplace because coordinates is already a copy + self.convert_pos_to_native( + coordinates + ) # inplace because coordinates is already a copy # Check atom attributes # required: @@ -266,11 +276,11 @@ def write(self, selection, frame=None): attrs = {} missing_topology = [] for attr, dflt in ( - ('names', itertools.cycle(('X',))), - ('resnames', itertools.cycle(('UNK',))), - ('resids', itertools.cycle((1,))), - ('charges', itertools.cycle((0.0,))), - ('radii', itertools.cycle((1.0,))), + ("names", itertools.cycle(("X",))), + ("resnames", itertools.cycle(("UNK",))), + ("resids", itertools.cycle((1,))), + ("charges", itertools.cycle((0.0,))), + ("radii", itertools.cycle((1.0,))), ): try: attrs[attr] = getattr(atoms, attr) @@ -283,16 +293,16 @@ def write(self, selection, frame=None): # if neither, use ' ' # if 'SYSTEM', use ' ' try: - attrs['chainids'] = atoms.chainids + attrs["chainids"] = atoms.chainids except AttributeError: try: - attrs['chainids'] = atoms.segids + attrs["chainids"] = atoms.segids except AttributeError: pass - if not 'chainids' in attrs or all(attrs['chainids'] == 'SYSTEM'): - attrs['chainids'] = itertools.cycle((' ',)) + if not "chainids" in attrs or all(attrs["chainids"] == "SYSTEM"): + attrs["chainids"] = itertools.cycle((" ",)) - if 'charges' in missing_topology: + if "charges" in missing_topology: total_charge = 0.0 else: total_charge = atoms.total_charge() @@ -301,28 +311,62 @@ def write(self, selection, frame=None): warnings.warn( "Supplied AtomGroup was missing the following attributes: " "{miss}. These will be written with default values. " - "".format(miss=', '.join(missing_topology))) + "".format(miss=", ".join(missing_topology)) + ) - with util.openany(self.filename, 'wt') as pqrfile: + with util.openany(self.filename, "wt") as pqrfile: # Header / Remarks # The *remarknumber* is typically 1 but :program:`pdb2pgr` # also uses 6 for the total charge and 5 for warnings. for rem in util.asiterable(self.remarks): pqrfile.write(self.fmt_remark.format(rem, 1)) - pqrfile.write(self.fmt_remark.format( - "Input: frame {0} of {1}".format(frame, u.trajectory.filename), - 5)) - pqrfile.write(self.fmt_remark.format( - "total charge: {0:+8.4f} e".format(total_charge), 6)) + pqrfile.write( + self.fmt_remark.format( + "Input: frame {0} of {1}".format( + frame, u.trajectory.filename + ), + 5, + ) + ) + pqrfile.write( + self.fmt_remark.format( + "total charge: {0:+8.4f} e".format(total_charge), 6 + ) + ) # Atom descriptions and coords - for atom_index, (pos, name, resname, chainid, resid, charge, radius) in enumerate(zip( - coordinates, attrs['names'], attrs['resnames'], attrs['chainids'], - attrs['resids'], attrs['charges'], attrs['radii']), start=1): + for atom_index, ( + pos, + name, + resname, + chainid, + resid, + charge, + radius, + ) in enumerate( + zip( + coordinates, + attrs["names"], + attrs["resnames"], + attrs["chainids"], + attrs["resids"], + attrs["charges"], + attrs["radii"], + ), + start=1, + ): # pad so that only 4-letter atoms are left-aligned name = " " + name if len(name) < 4 else name - pqrfile.write(self.fmt_ATOM.format( - serial=atom_index, name=name, resname=resname, - chainid=chainid, resid=resid, pos=pos, charge=charge, - radius=radius)) + pqrfile.write( + self.fmt_ATOM.format( + serial=atom_index, + name=name, + resname=resname, + chainid=chainid, + resid=resid, + pos=pos, + charge=charge, + radius=radius, + ) + ) diff --git a/package/MDAnalysis/coordinates/ParmEd.py b/package/MDAnalysis/coordinates/ParmEd.py index af29340a5d..982231c11a 100644 --- a/package/MDAnalysis/coordinates/ParmEd.py +++ b/package/MDAnalysis/coordinates/ParmEd.py @@ -21,13 +21,17 @@ # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # import warnings -from ..converters.ParmEd import (ParmEdConverter, ParmEdReader, - get_indices_from_subset, MDA2PMD,) +from ..converters.ParmEd import ( + ParmEdConverter, + ParmEdReader, + get_indices_from_subset, + MDA2PMD, +) warnings.warn( "This module is deprecated as of MDAnalysis version 2.0.0. " "It will be removed in MDAnalysis version 3.0.0. " "Please import the ParmEd classes from MDAnalysis.converters instead.", - category=DeprecationWarning + category=DeprecationWarning, ) diff --git a/package/MDAnalysis/coordinates/TNG.py b/package/MDAnalysis/coordinates/TNG.py index a5d868360f..44c6890dcf 100644 --- a/package/MDAnalysis/coordinates/TNG.py +++ b/package/MDAnalysis/coordinates/TNG.py @@ -148,7 +148,9 @@ 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 @@ -162,7 +164,9 @@ 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) @@ -193,27 +197,35 @@ 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 @@ -265,7 +277,9 @@ 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) @@ -289,7 +303,9 @@ 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 @@ -471,7 +487,9 @@ 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/TRC.py b/package/MDAnalysis/coordinates/TRC.py index 5d92db1af8..da43144870 100644 --- a/package/MDAnalysis/coordinates/TRC.py +++ b/package/MDAnalysis/coordinates/TRC.py @@ -259,7 +259,9 @@ 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 warnings.warn( @@ -296,7 +298,9 @@ def _read_GROMOS11_trajectory(self): tmp_buf.append(coords_str.split()) if np.array(tmp_buf).shape[0] == self.n_atoms: - frameDat["positions"] = np.asarray(tmp_buf, dtype=np.float64) + frameDat["positions"] = np.asarray( + tmp_buf, dtype=np.float64 + ) else: raise ValueError( "The trajectory contains the wrong number of atoms!" @@ -322,13 +326,19 @@ def _read_GROMOS11_trajectory(self): self.periodic = True gb_line3 = f.readline().split() - if np.sum(np.abs(np.array(gb_line3).astype(np.float64))) > 1e-10: + if ( + np.sum(np.abs(np.array(gb_line3).astype(np.float64))) + > 1e-10 + ): raise ValueError( "This reader doesnt't support a shifted origin!" ) gb_line4 = f.readline().split() - if np.sum(np.abs(np.array(gb_line4).astype(np.float64))) > 1e-10: + if ( + np.sum(np.abs(np.array(gb_line4).astype(np.float64))) + > 1e-10 + ): raise ValueError( "This reader " "doesnt't support " @@ -345,12 +355,14 @@ 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 == line.strip(): warnings.warn( - non_supp_bn + " block is not supported!", UserWarning + non_supp_bn + " block is not supported!", + UserWarning, ) return frameDat @@ -360,7 +372,9 @@ 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() @@ -381,7 +395,9 @@ def _reopen(self): def open_trajectory(self): if self.trcfile is not None: - raise IOError(errno.EALREADY, "TRC file already opened", self.filename) + raise IOError( + errno.EALREADY, "TRC file already opened", self.filename + ) # Reload trajectory file self.trcfile = util.anyopen(self.filename) diff --git a/package/MDAnalysis/coordinates/core.py b/package/MDAnalysis/coordinates/core.py index fe87cd005a..951ee3fd0a 100644 --- a/package/MDAnalysis/coordinates/core.py +++ b/package/MDAnalysis/coordinates/core.py @@ -73,15 +73,14 @@ def reader(filename, format=None, **kwargs): """ if isinstance(filename, tuple): - Reader = get_reader_for(filename[0], - format=filename[1]) + Reader = get_reader_for(filename[0], format=filename[1]) filename = filename[0] else: Reader = get_reader_for(filename, format=format) try: return Reader(filename, **kwargs) except ValueError: - errmsg = f'Unable to read {filename} with {Reader}.' + errmsg = f"Unable to read {filename} with {Reader}." raise TypeError(errmsg) from None @@ -121,6 +120,9 @@ def writer(filename, n_atoms=None, **kwargs): Added `multiframe` keyword. See also :func:`get_writer_for`. """ - Writer = get_writer_for(filename, format=kwargs.pop('format', None), - multiframe=kwargs.pop('multiframe', None)) + Writer = get_writer_for( + filename, + format=kwargs.pop("format", None), + multiframe=kwargs.pop("multiframe", None), + ) return Writer(filename, n_atoms=n_atoms, **kwargs) diff --git a/package/MDAnalysis/coordinates/null.py b/package/MDAnalysis/coordinates/null.py index 71b490aad2..5b2f4f1a3f 100644 --- a/package/MDAnalysis/coordinates/null.py +++ b/package/MDAnalysis/coordinates/null.py @@ -47,9 +47,10 @@ class NullWriter(base.WriterBase): a Writer but ignores all input. It can be used in order to suppress output. """ - format = 'NULL' + + format = "NULL" multiframe = True - units = {'time': 'ps', 'length': 'Angstrom'} + units = {"time": "ps", "length": "Angstrom"} def __init__(self, filename, **kwargs): pass diff --git a/package/pyproject.toml b/package/pyproject.toml index 413e4b6858..19d07228e7 100644 --- a/package/pyproject.toml +++ b/package/pyproject.toml @@ -137,6 +137,7 @@ tables\.py | MDAnalysis/transformations/.*\.py | MDAnalysis/guesser/.*\.py | MDAnalysis/converters/.*\.py +| MDAnalysis/coordinates/.*\.py | MDAnalysis/tests/.*\.py | MDAnalysis/selections/.*\.py ) @@ -186,6 +187,7 @@ __pycache__ | MDAnalysis/coordinates/chemfiles\.py | MDAnalysis/coordinates/memory\.py | MDAnalysis/core/universe\.py +| .*\.pyx ) ''' required-version = '24' diff --git a/testsuite/MDAnalysisTests/coordinates/base.py b/testsuite/MDAnalysisTests/coordinates/base.py index dafeeedca3..1568dfab87 100644 --- a/testsuite/MDAnalysisTests/coordinates/base.py +++ b/testsuite/MDAnalysisTests/coordinates/base.py @@ -26,8 +26,12 @@ import numpy as np import pytest from unittest import TestCase -from numpy.testing import (assert_equal, assert_almost_equal, - assert_array_almost_equal, assert_allclose) +from numpy.testing import ( + assert_equal, + assert_almost_equal, + assert_array_almost_equal, + assert_allclose, +) import MDAnalysis as mda from MDAnalysis.coordinates.timestep import Timestep @@ -48,41 +52,61 @@ def tearDown(self): def test_load_file(self): U = self.universe - assert_equal(len(U.atoms), self.ref_n_atoms, - "load Universe from file {0!s}".format(U.trajectory.filename)) - assert_equal(U.atoms.select_atoms('resid 150 and name HA2').atoms[0], - U.atoms[self.ref_E151HA2_index], "Atom selections") + assert_equal( + len(U.atoms), + self.ref_n_atoms, + "load Universe from file {0!s}".format(U.trajectory.filename), + ) + assert_equal( + U.atoms.select_atoms("resid 150 and name HA2").atoms[0], + U.atoms[self.ref_E151HA2_index], + "Atom selections", + ) def test_n_atoms(self): - assert_equal(self.universe.trajectory.n_atoms, self.ref_n_atoms, - "wrong number of atoms") + assert_equal( + self.universe.trajectory.n_atoms, + self.ref_n_atoms, + "wrong number of atoms", + ) 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(self.universe.trajectory.n_frames, 1, - "wrong number of frames in pdb") + assert_equal( + self.universe.trajectory.n_frames, + 1, + "wrong number of frames in pdb", + ) 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, + self.universe.trajectory.frame, + 0, "wrong frame number (0-based, should be 0 for single frame " - "readers)") + "readers)", + ) def test_frame_index_0(self): self.universe.trajectory[0] - assert_equal(self.universe.trajectory.ts.frame, 0, - "frame number for frame index 0 should be 0") + assert_equal( + self.universe.trajectory.ts.frame, + 0, + "frame number for frame index 0 should be 0", + ) def test_frame_index_1_raises_IndexError(self): def go_to_2(traj=self.universe.trajectory): traj[1] + with pytest.raises(IndexError): go_to_2() @@ -92,21 +116,25 @@ def test_dt(self): assert_equal(1.0, self.universe.trajectory.dt) def test_coordinates(self): - A10CA = self.universe.select_atoms('name CA')[10] + A10CA = self.universe.select_atoms("name CA")[10] # restrict accuracy to maximum in PDB files (3 decimals) - assert_almost_equal(A10CA.position, - self.ref_coordinates['A10CA'], - 3, - err_msg="wrong coordinates for A10:CA") + assert_almost_equal( + A10CA.position, + self.ref_coordinates["A10CA"], + 3, + err_msg="wrong coordinates for A10:CA", + ) def test_distances(self): - NTERM = self.universe.select_atoms('name N')[0] - CTERM = self.universe.select_atoms('name C')[-1] + NTERM = self.universe.select_atoms("name N")[0] + CTERM = self.universe.select_atoms("name C")[-1] d = mda.lib.mdamath.norm(NTERM.position - CTERM.position) - assert_almost_equal(d, - self.ref_distances['endtoend'], - self.prec, - err_msg="distance between M1:N and G214:C") + assert_almost_equal( + d, + self.ref_distances["endtoend"], + self.prec, + err_msg="distance between M1:N and G214:C", + ) def test_full_slice(self): trj_iter = self.universe.trajectory[:] @@ -124,15 +152,24 @@ def test_pickle_singleframe_reader(self): reader_p = pickle.loads(pickle.dumps(reader)) reader_p_p = pickle.loads(pickle.dumps(reader_p)) assert_equal(len(reader), len(reader_p)) - assert_equal(reader.ts, reader_p.ts, - "Single-frame timestep is changed after pickling") + assert_equal( + reader.ts, + reader_p.ts, + "Single-frame timestep is changed after pickling", + ) assert_equal(len(reader), len(reader_p_p)) - assert_equal(reader.ts, reader_p_p.ts, - "Single-frame timestep is changed after double pickling") + assert_equal( + reader.ts, + reader_p_p.ts, + "Single-frame timestep is changed after double pickling", + ) reader.ts.positions[0] = np.array([1, 2, 3]) reader_p = pickle.loads(pickle.dumps(reader)) - assert_equal(reader.ts, reader_p.ts, - "Modification of ts not preserved after serialization") + assert_equal( + reader.ts, + reader_p.ts, + "Modification of ts not preserved after serialization", + ) class BaseReference(object): @@ -149,58 +186,65 @@ def __init__(self): self.aux_lowf = AUX_XVG_LOWF # test auxiliary with lower frequency self.aux_lowf_dt = 2 # has steps at 0ps, 2ps, 4ps # representative data for each trajectory frame, assuming 'closest' option - self.aux_lowf_data = [[2 ** 0], # frame 0 = 0ps = step 0 - [np.nan], # frame 1 = 1ps = no step - [2 ** 1], # frame 2 = 2ps = step 1 - [np.nan], # frame 3 = 3ps = no step - [2 ** 2], # frame 4 = 4ps = step 2 - ] + self.aux_lowf_data = [ + [2**0], # frame 0 = 0ps = step 0 + [np.nan], # frame 1 = 1ps = no step + [2**1], # frame 2 = 2ps = step 1 + [np.nan], # frame 3 = 3ps = no step + [2**2], # frame 4 = 4ps = step 2 + ] self.aux_lowf_frames_with_steps = [0, 2, 4] # trajectory frames with # corresponding auxiliary steps self.aux_highf = AUX_XVG_HIGHF # test auxiliary with higher frequency self.aux_highf_dt = 0.5 # has steps at 0, 0.5, 1, ... 3.5, 4ps - self.aux_highf_data = [[2 ** 0], # frame 0 = 0ps = step 0 - [2 ** 2], # frame 1 = 1ps = step 2 - [2 ** 4], # frame 2 = 2ps = step 4 - [2 ** 6], # frame 3 = 3ps = step 6 - [2 ** 8], # frame 4 = 4ps = step 8 - ] + self.aux_highf_data = [ + [2**0], # frame 0 = 0ps = step 0 + [2**2], # frame 1 = 1ps = step 2 + [2**4], # frame 2 = 2ps = step 4 + [2**6], # frame 3 = 3ps = step 6 + [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 self.first_frame = Timestep(self.n_atoms) - self.first_frame.positions = np.arange( - 3 * self.n_atoms).reshape(self.n_atoms, 3) + self.first_frame.positions = np.arange(3 * self.n_atoms).reshape( + self.n_atoms, 3 + ) self.first_frame.frame = 0 self.first_frame.aux.lowf = self.aux_lowf_data[0] self.first_frame.aux.highf = self.aux_highf_data[0] self.second_frame = self.first_frame.copy() - self.second_frame.positions = 2 ** 1 * self.first_frame.positions + self.second_frame.positions = 2**1 * self.first_frame.positions self.second_frame.frame = 1 self.second_frame.aux.lowf = self.aux_lowf_data[1] self.second_frame.aux.highf = self.aux_highf_data[1] self.last_frame = self.first_frame.copy() - self.last_frame.positions = 2 ** 4 * self.first_frame.positions + self.last_frame.positions = 2**4 * self.first_frame.positions self.last_frame.frame = self.n_frames - 1 self.last_frame.aux.lowf = self.aux_lowf_data[-1] self.last_frame.aux.highf = self.aux_highf_data[-1] # remember frames are 0 indexed self.jump_to_frame = self.first_frame.copy() - self.jump_to_frame.positions = 2 ** 3 * self.first_frame.positions + self.jump_to_frame.positions = 2**3 * self.first_frame.positions self.jump_to_frame.frame = 3 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_second_frame = np.array([82.1, 83.2, 84.3, 75.1, 80.1, - 85.1], 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 + ) self.volume = mda.lib.mdamath.box_volume(self.dimensions) self.time = 0 self.dt = 1 @@ -208,7 +252,7 @@ def __init__(self): def iter_ts(self, i): ts = self.first_frame.copy() - ts.positions = 2 ** i * self.first_frame.positions + ts.positions = 2**i * self.first_frame.positions ts.time = i ts.frame = i ts.aux.lowf = np.array(self.aux_lowf_data[i]) @@ -221,15 +265,29 @@ class BaseReaderTest(object): @pytest.fixture() def reader(ref): reader = ref.reader(ref.trajectory) - reader.add_auxiliary('lowf', ref.aux_lowf, dt=ref.aux_lowf_dt, initial_time=0, time_selector=None) - reader.add_auxiliary('highf', ref.aux_highf, dt=ref.aux_highf_dt, initial_time=0, time_selector=None) + reader.add_auxiliary( + "lowf", + ref.aux_lowf, + dt=ref.aux_lowf_dt, + initial_time=0, + time_selector=None, + ) + reader.add_auxiliary( + "highf", + ref.aux_highf, + dt=ref.aux_highf_dt, + initial_time=0, + time_selector=None, + ) return reader @staticmethod @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_n_atoms(self, ref, reader): @@ -240,8 +298,9 @@ 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() @@ -250,14 +309,14 @@ def test_double_close(self, reader): def test_get_writer_1(self, ref, reader, tmpdir): with tmpdir.as_cwd(): - outfile = 'test-writer.' + ref.ext + outfile = "test-writer." + ref.ext with reader.Writer(outfile) as W: assert_equal(isinstance(W, ref.writer), True) assert_equal(W.n_atoms, reader.n_atoms) def test_get_writer_2(self, ref, reader, tmpdir): with tmpdir.as_cwd(): - outfile = 'test-writer.' + ref.ext + outfile = "test-writer." + ref.ext with reader.Writer(outfile, n_atoms=100) as W: assert_equal(isinstance(W, ref.writer), True) assert_equal(W.n_atoms, 100) @@ -276,9 +335,9 @@ def test_first_dimensions(self, ref, reader): if ref.dimensions is None: assert reader.ts.dimensions is None else: - assert_array_almost_equal(reader.ts.dimensions, - ref.dimensions, - decimal=ref.prec) + assert_array_almost_equal( + reader.ts.dimensions, ref.dimensions, decimal=ref.prec + ) def test_changing_dimensions(self, ref, reader): if ref.changing_dimensions: @@ -286,16 +345,18 @@ def test_changing_dimensions(self, ref, reader): if ref.dimensions is None: assert reader.ts.dimensions is None else: - assert_array_almost_equal(reader.ts.dimensions, - ref.dimensions, - decimal=ref.prec) + assert_array_almost_equal( + reader.ts.dimensions, ref.dimensions, decimal=ref.prec + ) reader[1] if ref.dimensions_second_frame is None: assert reader.ts.dimensions is None else: - assert_array_almost_equal(reader.ts.dimensions, - ref.dimensions_second_frame, - decimal=ref.prec) + assert_array_almost_equal( + reader.ts.dimensions, + ref.dimensions_second_frame, + decimal=ref.prec, + ) def test_volume(self, ref, reader): reader.rewind() @@ -306,47 +367,56 @@ def test_volume(self, ref, reader): def test_iter(self, ref, reader): for i, ts in enumerate(reader): - assert_timestep_almost_equal(ts, ref.iter_ts(i), - decimal=ref.prec) + assert_timestep_almost_equal(ts, ref.iter_ts(i), decimal=ref.prec) def test_add_same_auxname_raises_ValueError(self, ref, reader): with pytest.raises(ValueError): - reader.add_auxiliary('lowf', ref.aux_lowf) + reader.add_auxiliary("lowf", ref.aux_lowf) def test_remove_auxiliary(self, reader): - reader.remove_auxiliary('lowf') + reader.remove_auxiliary("lowf") with pytest.raises(AttributeError): - getattr(reader._auxs, 'lowf') + getattr(reader._auxs, "lowf") with pytest.raises(AttributeError): - getattr(reader.ts.aux, 'lowf') + getattr(reader.ts.aux, "lowf") def test_remove_nonexistant_auxiliary_raises_ValueError(self, reader): with pytest.raises(ValueError): - reader.remove_auxiliary('nonexistant') + reader.remove_auxiliary("nonexistant") def test_iter_auxiliary(self, ref, reader): # should go through all steps in 'highf' - for i, auxstep in enumerate(reader.iter_auxiliary('highf')): - assert_almost_equal(auxstep.data, ref.aux_highf_all_data[i], - err_msg="Auxiliary data does not match for " - "step {}".format(i)) + for i, auxstep in enumerate(reader.iter_auxiliary("highf")): + assert_almost_equal( + auxstep.data, + ref.aux_highf_all_data[i], + err_msg="Auxiliary data does not match for " + "step {}".format(i), + ) def test_get_aux_attribute(self, ref, reader): - assert_equal(reader.get_aux_attribute('lowf', 'dt'), - ref.aux_lowf_dt) + assert_equal(reader.get_aux_attribute("lowf", "dt"), ref.aux_lowf_dt) def test_iter_as_aux_cutoff(self, ref, reader): # load an auxiliary with the same dt but offset from trajectory, and a # cutoff of 0 - reader.add_auxiliary('offset', ref.aux_lowf, - dt=ref.dt, time_selector=None, - initial_time=ref.aux_offset_by, - cutoff=0) + reader.add_auxiliary( + "offset", + ref.aux_lowf, + dt=ref.dt, + time_selector=None, + initial_time=ref.aux_offset_by, + cutoff=0, + ) # no auxiliary steps will fall within the cutoff for any frame, so # iterating using iter_as_aux should give us nothing - num_frames = len([i for i in reader.iter_as_aux('offset')]) - assert_equal(num_frames, 0, "iter_as_aux should iterate over 0 frames," - " not {}".format(num_frames)) + num_frames = len([i for i in reader.iter_as_aux("offset")]) + assert_equal( + num_frames, + 0, + "iter_as_aux should iterate over 0 frames," + " not {}".format(num_frames), + ) def test_reload_auxiliaries_from_description(self, ref, reader): # get auxiliary desscriptions form existing reader @@ -357,12 +427,18 @@ def test_reload_auxiliaries_from_description(self, ref, reader): for aux in descriptions: reader.add_auxiliary(**aux) # should have the same number of auxiliaries - assert_equal(reader.aux_list, reader.aux_list, - 'Number of auxiliaries does not match') + assert_equal( + reader.aux_list, + reader.aux_list, + "Number of auxiliaries does not match", + ) # each auxiliary should be the same for auxname in reader.aux_list: - assert_equal(reader._auxs[auxname], reader._auxs[auxname], - 'AuxReaders do not match') + assert_equal( + reader._auxs[auxname], + reader._auxs[auxname], + "AuxReaders do not match", + ) def test_stop_iter(self, reader): # reset to 0 @@ -373,92 +449,122 @@ def test_stop_iter(self, reader): def test_transformations_iter(self, ref, transformed): # test one iteration and see if the transformations are applied - v1 = np.float32((1,1,1)) - v2 = np.float32((0,0,0.33)) + v1 = np.float32((1, 1, 1)) + v2 = np.float32((0, 0, 0.33)) for i, ts in enumerate(transformed): idealcoords = ref.iter_ts(i).positions + v1 + v2 - assert_array_almost_equal(ts.positions, idealcoords, decimal=ref.prec) + assert_array_almost_equal( + ts.positions, idealcoords, decimal=ref.prec + ) def test_transformations_2iter(self, ref, transformed): # Are the transformations applied and # are the coordinates "overtransformed"? - v1 = np.float32((1,1,1)) - v2 = np.float32((0,0,0.33)) - idealcoords=[] + v1 = np.float32((1, 1, 1)) + v2 = np.float32((0, 0, 0.33)) + idealcoords = [] for i, ts in enumerate(transformed): idealcoords.append(ref.iter_ts(i).positions + v1 + v2) - assert_array_almost_equal(ts.positions, idealcoords[i], decimal=ref.prec) + assert_array_almost_equal( + ts.positions, idealcoords[i], decimal=ref.prec + ) for i, ts in enumerate(transformed): assert_almost_equal(ts.positions, idealcoords[i], decimal=ref.prec) def test_transformations_slice(self, ref, transformed): # Are the transformations applied when iterating over a slice of the trajectory? - v1 = np.float32((1,1,1)) - v2 = np.float32((0,0,0.33)) - for i,ts in enumerate(transformed[2:3:1]): + v1 = np.float32((1, 1, 1)) + 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_array_almost_equal(ts.positions, idealcoords, decimal = ref.prec) + assert_array_almost_equal( + ts.positions, idealcoords, decimal=ref.prec + ) def test_transformations_switch_frame(self, ref, transformed): # This test checks if the transformations are applied and if the coordinates # "overtransformed" on different situations # Are the transformations applied when we switch to a different frame? - v1 = np.float32((1,1,1)) - v2 = np.float32((0,0,0.33)) + v1 = np.float32((1, 1, 1)) + v2 = np.float32((0, 0, 0.33)) first_ideal = ref.iter_ts(0).positions + v1 + v2 - if len(transformed)>1: - assert_array_almost_equal(transformed[0].positions, first_ideal, decimal = ref.prec) + if len(transformed) > 1: + assert_array_almost_equal( + transformed[0].positions, first_ideal, decimal=ref.prec + ) second_ideal = ref.iter_ts(1).positions + v1 + v2 - assert_array_almost_equal(transformed[1].positions, second_ideal, decimal = ref.prec) + assert_array_almost_equal( + transformed[1].positions, second_ideal, decimal=ref.prec + ) # What if we comeback to the previous frame? - assert_array_almost_equal(transformed[0].positions, first_ideal, decimal = ref.prec) + assert_array_almost_equal( + transformed[0].positions, first_ideal, decimal=ref.prec + ) # How about we switch the frame to itself? - assert_array_almost_equal(transformed[0].positions, first_ideal, decimal = ref.prec) + assert_array_almost_equal( + transformed[0].positions, first_ideal, decimal=ref.prec + ) else: - assert_array_almost_equal(transformed[0].positions, first_ideal, decimal = ref.prec) + assert_array_almost_equal( + transformed[0].positions, first_ideal, decimal=ref.prec + ) - def test_transformation_rewind(self,ref, transformed): + def test_transformation_rewind(self, ref, transformed): # this test checks if the transformations are applied after rewinding the # trajectory - v1 = np.float32((1,1,1)) - v2 = np.float32((0,0,0.33)) + v1 = np.float32((1, 1, 1)) + v2 = np.float32((0, 0, 0.33)) ideal_coords = ref.iter_ts(0).positions + v1 + v2 transformed.rewind() - assert_array_almost_equal(transformed[0].positions, ideal_coords, decimal = ref.prec) + assert_array_almost_equal( + transformed[0].positions, ideal_coords, decimal=ref.prec + ) - def test_transformations_copy(self,ref,transformed): + def test_transformations_copy(self, ref, transformed): # this test checks if transformations are carried over a copy and if the # coordinates of the copy are equal to the original's - v1 = np.float32((1,1,1)) - v2 = np.float32((0,0,0.33)) + v1 = np.float32((1, 1, 1)) + v2 = np.float32((0, 0, 0.33)) new = transformed.copy() - assert_equal(transformed.transformations, new.transformations, - "transformations are not equal") + assert_equal( + transformed.transformations, + new.transformations, + "transformations are not equal", + ) for i, ts in enumerate(new): ideal_coords = ref.iter_ts(i).positions + v1 + v2 - assert_array_almost_equal(ts.positions, ideal_coords, decimal = ref.prec) + assert_array_almost_equal( + ts.positions, ideal_coords, decimal=ref.prec + ) def test_add_another_transformations_raises_ValueError(self, transformed): # After defining the transformations, the workflow cannot be changed with pytest.raises(ValueError): - transformed.add_transformations(translate([2,2,2])) + transformed.add_transformations(translate([2, 2, 2])) 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(reader.ts, reader_p_p.ts, - "Timestep is changed after double pickling") + assert_equal( + reader.ts, + reader_p_p.ts, + "Timestep is changed after double pickling", + ) reader.ts.positions[0] = np.array([1, 2, 3]) reader_p = pickle.loads(pickle.dumps(reader)) - assert_equal(reader.ts, reader_p.ts, - "Modification of ts not preserved after serialization") + assert_equal( + reader.ts, + reader_p.ts, + "Modification of ts not preserved after serialization", + ) def test_frame_collect_all_same(self, reader): # check that the timestep resets so that the base reference is the same @@ -467,83 +573,105 @@ def test_frame_collect_all_same(self, reader): if isinstance(reader, mda.coordinates.memory.MemoryReader): pytest.xfail("memoryreader allows independent coordinates") if isinstance(reader, mda.coordinates.DCD.DCDReader): - pytest.xfail("DCDReader allows independent coordinates." - "This behaviour is deprecated and will be changed" - "in 3.0") + pytest.xfail( + "DCDReader allows independent coordinates." + "This behaviour is deprecated and will be changed" + "in 3.0" + ) collected_ts = [] for i, ts in enumerate(reader): collected_ts.append(ts.positions) - for array in collected_ts: + 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') - f_index = order.index('f') - c_index = order.index('c') - assert(timeseries.shape[a_index] == reader.n_atoms) - assert(timeseries.shape[f_index] == len(reader)) - assert(timeseries.shape[c_index] == 3) - - @pytest.mark.parametrize('slice', ([0,2,1], [0,10,2], [0,10,3])) + a_index = order.index("a") + f_index = order.index("f") + c_index = order.index("c") + assert timeseries.shape[a_index] == reader.n_atoms + assert timeseries.shape[f_index] == len(reader) + assert timeseries.shape[c_index] == 3 + + @pytest.mark.parametrize("slice", ([0, 2, 1], [0, 10, 2], [0, 10, 3])) def test_timeseries_values(self, reader, slice): ts_positions = [] if isinstance(reader, mda.coordinates.memory.MemoryReader): - pytest.xfail("MemoryReader uses deprecated stop inclusive" - " indexing, see Issue #3893") + pytest.xfail( + "MemoryReader uses deprecated stop inclusive" + " indexing, see Issue #3893" + ) if slice[1] > len(reader): pytest.skip("too few frames in reader") for i in range(slice[0], slice[1], slice[2]): ts = reader[i] ts_positions.append(ts.positions.copy()) positions = np.asarray(ts_positions) - timeseries = reader.timeseries(start=slice[0], stop=slice[1], - step=slice[2], order='fac') + timeseries = reader.timeseries( + start=slice[0], stop=slice[1], step=slice[2], order="fac" + ) assert_allclose(timeseries, positions) - @pytest.mark.parametrize('asel', ("index 1", "index 2", "index 1 to 3")) + @pytest.mark.parametrize("asel", ("index 1", "index 2", "index 1 to 3")) def test_timeseries_asel_shape(self, reader, asel): atoms = mda.Universe(reader.filename, to_guess=()).select_atoms(asel) - timeseries = reader.timeseries(atoms, order='fac') - assert(timeseries.shape[0] == len(reader)) - assert(timeseries.shape[1] == len(atoms)) - assert(timeseries.shape[2] == 3) + timeseries = reader.timeseries(atoms, order="fac") + assert timeseries.shape[0] == len(reader) + assert timeseries.shape[1] == len(atoms) + assert timeseries.shape[2] == 3 def test_timeseries_empty_asel(self, reader): - with pytest.warns(UserWarning, - match="Empty string to select atoms, empty group returned."): - atoms = mda.Universe(reader.filename, to_guess=()).select_atoms(None) + with pytest.warns( + UserWarning, + match="Empty string to select atoms, empty group returned.", + ): + atoms = mda.Universe(reader.filename, to_guess=()).select_atoms( + None + ) with pytest.raises(ValueError, match="Timeseries requires at least"): reader.timeseries(asel=atoms) def test_timeseries_empty_atomgroup(self, reader): - with pytest.warns(UserWarning, - match="Empty string to select atoms, empty group returned."): - atoms = mda.Universe(reader.filename, to_guess=()).select_atoms(None) + with pytest.warns( + UserWarning, + match="Empty string to select atoms, empty group returned.", + ): + 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') + timeseries = reader.timeseries(asel=atoms, order="fac") def test_timeseries_atomgroup(self, reader): - atoms = mda.Universe(reader.filename, to_guess=()).select_atoms("index 1") - timeseries = reader.timeseries(atomgroup=atoms, order='fac') + 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): def test_last_frame(self, ref, reader): ts = reader[-1] - assert_timestep_almost_equal(ts, ref.last_frame, - decimal=ref.prec) + assert_timestep_almost_equal(ts, ref.last_frame, decimal=ref.prec) def test_go_over_last_frame(self, ref, reader): with pytest.raises(IndexError): @@ -551,8 +679,7 @@ def test_go_over_last_frame(self, ref, reader): def test_frame_jump(self, ref, reader): ts = reader[ref.jump_to_frame.frame] - assert_timestep_almost_equal(ts, ref.jump_to_frame, - decimal=ref.prec) + assert_timestep_almost_equal(ts, ref.jump_to_frame, decimal=ref.prec) def test_frame_jump_issue1942(self, ref, reader): """Test for issue 1942 (especially XDR on macOS)""" @@ -566,49 +693,50 @@ def test_frame_jump_issue1942(self, ref, reader): def test_next_gives_second_frame(self, ref, reader): reader = ref.reader(ref.trajectory) ts = reader.next() - assert_timestep_almost_equal(ts, ref.second_frame, - decimal=ref.prec) + assert_timestep_almost_equal(ts, ref.second_frame, decimal=ref.prec) def test_reopen(self, ref, reader): reader.close() reader._reopen() ts = reader.next() - assert_timestep_almost_equal(ts, ref.first_frame, - decimal=ref.prec) + assert_timestep_almost_equal(ts, ref.first_frame, decimal=ref.prec) def test_rename_aux(self, ref, reader): - reader.rename_aux('lowf', 'lowf_renamed') + reader.rename_aux("lowf", "lowf_renamed") # data should now be in aux namespace under new name - assert_equal(reader.ts.aux.lowf_renamed, - ref.aux_lowf_data[0]) + assert_equal(reader.ts.aux.lowf_renamed, ref.aux_lowf_data[0]) # old name should be removed with pytest.raises(AttributeError): - getattr(reader.ts.aux, 'lowf') + getattr(reader.ts.aux, "lowf") # new name should be retained next(reader) - assert_equal(reader.ts.aux.lowf_renamed, - ref.aux_lowf_data[1]) + assert_equal(reader.ts.aux.lowf_renamed, ref.aux_lowf_data[1]) def test_iter_as_aux_highf(self, ref, reader): # auxiliary has a higher frequency, so iter_as_aux should behave the # same as regular iteration over the trjectory - for i, ts in enumerate(reader.iter_as_aux('highf')): - assert_timestep_almost_equal(ts, ref.iter_ts(i), - decimal=ref.prec) + for i, ts in enumerate(reader.iter_as_aux("highf")): + assert_timestep_almost_equal(ts, ref.iter_ts(i), decimal=ref.prec) def test_iter_as_aux_lowf(self, ref, reader): # auxiliary has a lower frequency, so iter_as_aux should iterate over # only frames where there is a corresponding auxiliary value - for i, ts in enumerate(reader.iter_as_aux('lowf')): - assert_timestep_almost_equal(ts, - ref.iter_ts(ref.aux_lowf_frames_with_steps[i]), - decimal=ref.prec) - - @pytest.mark.parametrize("accessor", [ - lambda traj: traj[[0, 1, 2]], - lambda traj: traj[:3], - lambda traj: traj], - ids=["indexed", "sliced", "all"]) + for i, ts in enumerate(reader.iter_as_aux("lowf")): + assert_timestep_almost_equal( + ts, + ref.iter_ts(ref.aux_lowf_frames_with_steps[i]), + decimal=ref.prec, + ) + + @pytest.mark.parametrize( + "accessor", + [ + lambda traj: traj[[0, 1, 2]], + lambda traj: traj[:3], + lambda traj: traj, + ], + ids=["indexed", "sliced", "all"], + ) def test_iter_rewinds(self, reader, accessor): for ts_indices in accessor(reader): pass @@ -618,21 +746,31 @@ def test_iter_rewinds(self, reader, accessor): # but also maintain its relative position. def test_pickle_next_ts_reader(self, reader): reader_p = pickle.loads(pickle.dumps(reader)) - assert_equal(next(reader), next(reader_p), - "Next timestep is changed after pickling") + assert_equal( + next(reader), + next(reader_p), + "Next timestep is changed after pickling", + ) reader_p_p = pickle.loads(pickle.dumps(reader_p)) - assert_equal(next(reader), next(reader_p_p), - "Next timestep is changed after double pickling") + assert_equal( + next(reader), + next(reader_p_p), + "Next timestep is changed after double pickling", + ) # To make sure pickle works for last frame. def test_pickle_last_ts_reader(self, reader): # move current ts to last frame. reader[-1] reader_p = pickle.loads(pickle.dumps(reader)) - assert_equal(len(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( + len(reader), + len(reader_p), + "Last timestep is changed after pickling", + ) + assert_equal( + reader.ts, reader_p.ts, "Last timestep is changed after pickling" + ) class BaseWriterTest(object): @@ -644,18 +782,17 @@ def reader(ref): @staticmethod @pytest.fixture() def u_no_resnames(): - return make_Universe(['names', 'resids'], trajectory=True) + return make_Universe(["names", "resids"], trajectory=True) @staticmethod @pytest.fixture() def u_no_resids(): - return make_Universe(['names', 'resnames'], trajectory=True) + return make_Universe(["names", "resnames"], trajectory=True) @staticmethod @pytest.fixture() def u_no_names(): - return make_Universe(['resids', 'resnames'], - trajectory=True) + return make_Universe(["resids", "resnames"], trajectory=True) @staticmethod @pytest.fixture() @@ -664,7 +801,7 @@ def universe(ref): def test_write_different_box(self, ref, universe, tmpdir): if ref.changing_dimensions: - outfile = 'write-dimensions-test' + ref.ext + outfile = "write-dimensions-test" + ref.ext with tmpdir.as_cwd(): with ref.writer(outfile, universe.atoms.n_atoms) as W: for ts in universe.trajectory: @@ -675,12 +812,12 @@ def test_write_different_box(self, ref, universe, tmpdir): for ts_ref, ts_w in zip(universe.trajectory, written): universe.dimensions[:3] += 1 - assert_array_almost_equal(universe.dimensions, - ts_w.dimensions, - decimal=ref.prec) + assert_array_almost_equal( + universe.dimensions, ts_w.dimensions, decimal=ref.prec + ) - def test_write_trajectory_atomgroup(self, ref,reader, universe, tmpdir): - outfile = 'write-atoms-test.' + ref.ext + def test_write_trajectory_atomgroup(self, ref, reader, universe, tmpdir): + outfile = "write-atoms-test." + ref.ext with tmpdir.as_cwd(): with ref.writer(outfile, universe.atoms.n_atoms) as w: for ts in universe.trajectory: @@ -688,19 +825,26 @@ def test_write_trajectory_atomgroup(self, ref,reader, universe, tmpdir): self._check_copy(outfile, ref, reader) def test_write_trajectory_universe(self, ref, reader, universe, tmpdir): - outfile = 'write-uni-test.' + ref.ext + outfile = "write-uni-test." + ref.ext with tmpdir.as_cwd(): with ref.writer(outfile, universe.atoms.n_atoms) as w: for ts in universe.trajectory: w.write(universe) self._check_copy(outfile, ref, reader) - def test_write_selection(self, ref, reader, universe, u_no_resnames, - u_no_resids, u_no_names, tmpdir): - sel_str = 'resid 1' + def test_write_selection( + self, + ref, + reader, + universe, + u_no_resnames, + u_no_resids, + u_no_names, + tmpdir, + ): + sel_str = "resid 1" sel = universe.select_atoms(sel_str) - outfile = 'write-selection-test.' + ref.ext - + outfile = "write-selection-test." + ref.ext with tmpdir.as_cwd(): with ref.writer(outfile, sel.n_atoms) as W: @@ -710,20 +854,23 @@ def test_write_selection(self, ref, reader, universe, u_no_resnames, copy = ref.reader(outfile) for orig_ts, copy_ts in zip(universe.trajectory, copy): assert_array_almost_equal( - copy_ts._pos, sel.atoms.positions, ref.prec, + copy_ts._pos, + sel.atoms.positions, + ref.prec, err_msg="coordinate mismatch between original and written " - "trajectory at frame {} (orig) vs {} (copy)".format( - orig_ts.frame, copy_ts.frame)) + "trajectory at frame {} (orig) vs {} (copy)".format( + orig_ts.frame, copy_ts.frame + ), + ) def _check_copy(self, fname, ref, reader): copy = ref.reader(fname) assert_equal(reader.n_frames, copy.n_frames) for orig_ts, copy_ts in zip(reader, copy): - assert_timestep_almost_equal( - copy_ts, orig_ts, decimal=ref.prec) + assert_timestep_almost_equal(copy_ts, orig_ts, decimal=ref.prec) def test_write_none(self, ref, tmpdir): - outfile = 'write-none.' + ref.ext + outfile = "write-none." + ref.ext with tmpdir.as_cwd(): with pytest.raises(TypeError): with ref.writer(outfile, 42) as w: @@ -732,13 +879,13 @@ def test_write_none(self, ref, tmpdir): def test_no_container(self, ref, tmpdir): with tmpdir.as_cwd(): if ref.container_format: - ref.writer('foo') + ref.writer("foo") else: with pytest.raises(TypeError): - ref.writer('foo') + ref.writer("foo") def test_write_not_changing_ts(self, ref, universe, tmpdir): - outfile = 'write-not-changing-ts.' + ref.ext + outfile = "write-not-changing-ts." + ref.ext copy_ts = universe.trajectory.ts.copy() with tmpdir.as_cwd(): @@ -747,63 +894,91 @@ def test_write_not_changing_ts(self, ref, universe, tmpdir): assert_timestep_almost_equal(copy_ts, universe.trajectory.ts) -def assert_timestep_equal(A, B, msg=''): - """ assert that two timesteps are exactly equal and commutative - """ +def assert_timestep_equal(A, B, msg=""): + """assert that two timesteps are exactly equal and commutative""" assert A == B, msg assert B == A, msg def assert_timestep_almost_equal(A, B, decimal=6, verbose=True): if not isinstance(A, mda.coordinates.timestep.Timestep): - raise AssertionError('A is not of type Timestep') + raise AssertionError("A is not of type Timestep") if not isinstance(B, mda.coordinates.timestep.Timestep): - raise AssertionError('B is not of type Timestep') + raise AssertionError("B is not of type Timestep") if A.frame != B.frame: - raise AssertionError('A and B refer to different frames: ' - 'A.frame = {}, B.frame={}'.format( - A.frame, B.frame)) + raise AssertionError( + "A and B refer to different frames: " + "A.frame = {}, B.frame={}".format(A.frame, B.frame) + ) if not np.allclose(A.time, B.time): - raise AssertionError('A and B refer to different times: ' - 'A.time = {}, B.time={}'.format( - A.time, B.time)) + raise AssertionError( + "A and B refer to different times: " + "A.time = {}, B.time={}".format(A.time, B.time) + ) if A.n_atoms != B.n_atoms: - raise AssertionError('A and B have a differnent number of atoms: ' - 'A.n_atoms = {}, B.n_atoms = {}'.format( - A.n_atoms, B.n_atoms)) + raise AssertionError( + "A and B have a differnent number of atoms: " + "A.n_atoms = {}, B.n_atoms = {}".format(A.n_atoms, B.n_atoms) + ) if A.has_positions != B.has_positions: - raise AssertionError('Only one Timestep has positions:' - 'A.has_positions = {}, B.has_positions = {}'.format( - A.has_positions, B.has_positions)) + raise AssertionError( + "Only one Timestep has positions:" + "A.has_positions = {}, B.has_positions = {}".format( + A.has_positions, B.has_positions + ) + ) if A.has_positions: - assert_array_almost_equal(A.positions, B.positions, decimal=decimal, - err_msg='Timestep positions', - verbose=verbose) + assert_array_almost_equal( + A.positions, + B.positions, + decimal=decimal, + err_msg="Timestep positions", + verbose=verbose, + ) if A.has_velocities != B.has_velocities: - raise AssertionError('Only one Timestep has velocities:' - 'A.has_velocities = {}, B.has_velocities = {}'.format( - A.has_velocities, B.has_velocities)) + raise AssertionError( + "Only one Timestep has velocities:" + "A.has_velocities = {}, B.has_velocities = {}".format( + A.has_velocities, B.has_velocities + ) + ) if A.has_velocities: - assert_array_almost_equal(A.velocities, B.velocities, decimal=decimal, - err_msg='Timestep velocities', - verbose=verbose) + assert_array_almost_equal( + A.velocities, + B.velocities, + decimal=decimal, + err_msg="Timestep velocities", + verbose=verbose, + ) 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)) + raise AssertionError( + "Only one Timestep has forces:" + "A.has_forces = {}, B.has_forces = {}".format( + A.has_forces, B.has_forces + ) + ) if A.has_forces: - assert_array_almost_equal(A.forces, B.forces, decimal=decimal, - err_msg='Timestep forces', verbose=verbose) + assert_array_almost_equal( + A.forces, + B.forces, + decimal=decimal, + err_msg="Timestep forces", + verbose=verbose, + ) # Check we've got auxiliaries before comparing values (auxiliaries aren't written # so we won't have aux values to compare when testing writer) if len(A.aux) > 0 and len(B.aux) > 0: - assert_equal(A.aux, B.aux, err_msg='Auxiliary values do not match: ' - 'A.aux = {}, B.aux = {}'.format(A.aux, B.aux)) + assert_equal( + A.aux, + B.aux, + err_msg="Auxiliary values do not match: " + "A.aux = {}, B.aux = {}".format(A.aux, B.aux), + ) diff --git a/testsuite/MDAnalysisTests/coordinates/reference.py b/testsuite/MDAnalysisTests/coordinates/reference.py index 73a9180985..8d43a9f925 100644 --- a/testsuite/MDAnalysisTests/coordinates/reference.py +++ b/testsuite/MDAnalysisTests/coordinates/reference.py @@ -23,12 +23,19 @@ import numpy as np from MDAnalysisTests import datafiles -from MDAnalysisTests.datafiles import (PDB_small, PDB, LAMMPSdata, - LAMMPSdata2, LAMMPSdcd2, - LAMMPSdata_mini, - LAMMPSdata_additional_columns, - PSF_TRICLINIC, DCD_TRICLINIC, - PSF_NAMD_TRICLINIC, DCD_NAMD_TRICLINIC) +from MDAnalysisTests.datafiles import ( + PDB_small, + PDB, + LAMMPSdata, + LAMMPSdata2, + LAMMPSdcd2, + LAMMPSdata_mini, + LAMMPSdata_additional_columns, + PSF_TRICLINIC, + DCD_TRICLINIC, + PSF_NAMD_TRICLINIC, + DCD_NAMD_TRICLINIC, +) class RefAdKSmall(object): @@ -41,20 +48,22 @@ class RefAdKSmall(object): All distances must be in ANGSTROEM as this is the MDAnalysis default unit. All readers must return Angstroem by default. """ + filename = datafiles.PDB_small ref_coordinates = { # G11:CA, copied frm adk_open.pdb - 'A10CA': np.array([-1.198, 7.937, 22.654]), + "A10CA": np.array([-1.198, 7.937, 22.654]), } - ref_distances = {'endtoend': 11.016959} + ref_distances = {"endtoend": 11.016959} ref_E151HA2_index = 2314 ref_n_atoms = 3341 ref_charmm_totalcharge = -4.0 ref_charmm_Hcharges = [0.33] + 203 * [0.31] ref_charmm_ArgCAcharges = 13 * [0.07] ref_charmm_ProNcharges = 10 * [-0.29] - ref_unitcell = np.array([80.017, 80.017, 80.017, 60., 60., 90.], - dtype=np.float32) + ref_unitcell = np.array( + [80.017, 80.017, 80.017, 60.0, 60.0, 90.0], dtype=np.float32 + ) ref_volume = 0.0 @@ -68,19 +77,21 @@ class RefAdK(object): All distances must be in ANGSTROEM as this is the MDAnalysis default unit. All readers must return Angstroem by default. """ + filename = datafiles.PDB ref_coordinates = { # Angstroem as MDAnalysis unit!! - 'A10CA': np.array([62.97600174, 62.08800125, 20.2329998]), + "A10CA": np.array([62.97600174, 62.08800125, 20.2329998]), } - ref_distances = {'endtoend': 9.3513174} + ref_distances = {"endtoend": 9.3513174} ref_E151HA2_index = 2314 ref_n_atoms = 47681 ref_Na_sel_size = 4 # CRYST1 80.017 80.017 80.017 60.00 60.00 90.00 - ref_unitcell = np.array([80.017, 80.017, 80.017, 60., 60., 90.], - dtype=np.float32) - #ref_volume = 362270.0 # computed with Gromacs ## NOT EXACT! + ref_unitcell = np.array( + [80.017, 80.017, 80.017, 60.0, 60.0, 90.0], dtype=np.float32 + ) + # ref_volume = 362270.0 # computed with Gromacs ## NOT EXACT! ref_volume = 362269.520669292 @@ -94,6 +105,7 @@ class Ref2r9r(object): All distances must be in ANGSTROEM as this is the MDAnalysis default unit. All readers must return Angstroem by default. """ + ref_n_atoms = 1284 ref_sum_centre_of_geometry = -98.24146 ref_n_frames = 10 @@ -115,6 +127,7 @@ class RefACHE(object): # 472.2592159509659 """ + ref_n_atoms = 252 ref_proteinatoms = ref_n_atoms ref_sum_centre_of_geometry = 472.2592159509659 # 430.44807815551758 @@ -138,6 +151,7 @@ class RefCappedAla(object): # 686.276834487915 """ + ref_n_atoms = 5071 ref_proteinatoms = 22 ref_sum_centre_of_geometry = 686.276834487915 @@ -155,6 +169,7 @@ class RefVGV(object): ref_sum_centre_of_geometry = np.sum([protein.center_of_geometry() for ts in w.trajectory]) """ + topology = datafiles.PRMncdf filename = datafiles.NCDF ref_n_atoms = 2661 @@ -163,11 +178,13 @@ class RefVGV(object): ref_n_frames = 30 ref_periodic = True + class RefTZ2(object): """Reference values for the cpptraj testcase tz2.truncoct.nc Used under the GPL v3. """ + topology = datafiles.PRM7 filename = datafiles.NCDFtruncoct ref_n_atoms = 5827 @@ -175,37 +192,53 @@ class RefTZ2(object): ref_sum_centre_of_geometry = -68.575745 ref_n_frames = 10 ref_periodic = True - + class RefTRZ(object): # ref_coordinates = {} # ref_distances = {'endtoend': } ref_n_atoms = 8184 - ref_dimensions = np.array([55.422830581665039, 55.422830581665039, - 55.422830581665039, 90., 90., 90.], - dtype=np.float32) + ref_dimensions = np.array( + [ + 55.422830581665039, + 55.422830581665039, + 55.422830581665039, + 90.0, + 90.0, + 90.0, + ], + dtype=np.float32, + ) ref_volume = 170241.762765 ref_n_frames = 6 - ref_coordinates = np.array([72.3163681, -130.31130981, 19.97969055], - dtype=np.float32) - ref_velocities = np.array([[14.83297443, 18.02611542, 6.07733774]], - dtype=np.float32) + ref_coordinates = np.array( + [72.3163681, -130.31130981, 19.97969055], dtype=np.float32 + ) + ref_velocities = np.array( + [[14.83297443, 18.02611542, 6.07733774]], dtype=np.float32 + ) ref_delta = 0.001 ref_time = 0.01 - ref_title = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234' - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234') + ref_title = ( + "ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234" + ) class RefLAMMPSData(object): filename = LAMMPSdata n_atoms = 18364 - pos_atom1 = np.array([11.89985657, 48.4455719, 19.09719849], - dtype=np.float32) - vel_atom1 = np.array([-0.005667593, 0.00791380978, -0.00300779533], - dtype=np.float32) - dimensions = np.array([55.42282867, 55.42282867, 55.42282867, 90., 90., 90. - ], - dtype=np.float32) + pos_atom1 = np.array( + [11.89985657, 48.4455719, 19.09719849], dtype=np.float32 + ) + vel_atom1 = np.array( + [-0.005667593, 0.00791380978, -0.00300779533], dtype=np.float32 + ) + dimensions = np.array( + [55.42282867, 55.42282867, 55.42282867, 90.0, 90.0, 90.0], + dtype=np.float32, + ) + class RefLAMMPSDataDCD(object): format = "LAMMPS" @@ -215,22 +248,38 @@ class RefLAMMPSDataDCD(object): n_frames = 5 dt = 0.5 # ps per frame mean_dimensions = np.array( - [ 50.66186142, 47.18824387, 52.33762741, - 90. , 90. , 90. ], dtype=np.float32) + [50.66186142, 47.18824387, 52.33762741, 90.0, 90.0, 90.0], + dtype=np.float32, + ) class RefLAMMPSDataMini(object): filename = LAMMPSdata_mini n_atoms = 1 - pos_atom1 = np.array([11.89985657, 48.4455719, 19.09719849], - dtype=np.float32) - vel_atom1 = np.array([-0.005667593, 0.00791380978, -0.00300779533], - dtype=np.float32) - dimensions = np.array([60., 50., 30., 90., 90., 90.], dtype=np.float32) + pos_atom1 = np.array( + [11.89985657, 48.4455719, 19.09719849], dtype=np.float32 + ) + vel_atom1 = np.array( + [-0.005667593, 0.00791380978, -0.00300779533], dtype=np.float32 + ) + dimensions = np.array( + [60.0, 50.0, 30.0, 90.0, 90.0, 90.0], dtype=np.float32 + ) class RefLAMMPSDataAdditionalColumns(object): - q = np.array([2.58855e-03, 6.91952e-05, 1.05548e-02, 4.20319e-03, - 9.19172e-03, 4.79777e-03, 6.36864e-04, 5.87125e-03, - -2.18125e-03, 6.88910e-03]) + q = np.array( + [ + 2.58855e-03, + 6.91952e-05, + 1.05548e-02, + 4.20319e-03, + 9.19172e-03, + 4.79777e-03, + 6.36864e-04, + 5.87125e-03, + -2.18125e-03, + 6.88910e-03, + ] + ) p = np.array(5 * [1.1, 1.2]) diff --git a/testsuite/MDAnalysisTests/coordinates/test_amber_inpcrd.py b/testsuite/MDAnalysisTests/coordinates/test_amber_inpcrd.py index 66394ee4d7..9fb8fe29ea 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_amber_inpcrd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_amber_inpcrd.py @@ -22,10 +22,10 @@ # import numpy as np -from numpy.testing import (assert_allclose, assert_equal) +from numpy.testing import assert_allclose, assert_equal import MDAnalysis as mda -from MDAnalysisTests.datafiles import (INPCRD, XYZ_five) +from MDAnalysisTests.datafiles import INPCRD, XYZ_five class TestINPCRDReader(object): @@ -34,16 +34,21 @@ class TestINPCRDReader(object): @staticmethod def _check_ts(ts): # Check a ts has the right values in - ref_pos = np.array([[6.6528795, 6.6711416, -8.5963255], - [7.3133773, 5.8359736, -8.8294175], - [8.3254058, 6.2227613, -8.7098593], - [7.0833200, 5.5038197, -9.8417650], - [7.1129439, 4.6170351, -7.9729560]]) + ref_pos = np.array( + [ + [6.6528795, 6.6711416, -8.5963255], + [7.3133773, 5.8359736, -8.8294175], + [8.3254058, 6.2227613, -8.7098593], + [7.0833200, 5.5038197, -9.8417650], + [7.1129439, 4.6170351, -7.9729560], + ] + ) for ref, val in zip(ref_pos, ts._pos): assert_allclose(ref, val) def test_reader(self): from MDAnalysis.coordinates.INPCRD import INPReader + r = INPReader(INPCRD) assert_equal(r.n_atoms, 5) self._check_ts(r.ts) @@ -53,5 +58,5 @@ def test_universe_inpcrd(self): self._check_ts(u.trajectory.ts) def test_universe_restrt(self): - u = mda.Universe(XYZ_five, INPCRD, format='RESTRT') + u = mda.Universe(XYZ_five, INPCRD, format="RESTRT") self._check_ts(u.trajectory.ts) diff --git a/testsuite/MDAnalysisTests/coordinates/test_chainreader.py b/testsuite/MDAnalysisTests/coordinates/test_chainreader.py index 84bcd128cf..4614e3e4d1 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_chainreader.py +++ b/testsuite/MDAnalysisTests/coordinates/test_chainreader.py @@ -20,22 +20,31 @@ # MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # -import sys +import os import platform +import sys import warnings -import numpy as np -import os - -import pytest - -from numpy.testing import (assert_equal, assert_almost_equal) import MDAnalysis as mda +import numpy as np +import pytest from MDAnalysis.transformations import translate -from MDAnalysisTests.datafiles import (PDB, PSF, CRD, DCD, - GRO, XTC, TRR, PDB_small, PDB_closed, - LAMMPS_chain, LAMMPSDUMP_chain1, - LAMMPSDUMP_chain2,) +from numpy.testing import assert_almost_equal, assert_equal + +from MDAnalysisTests.datafiles import ( + CRD, + DCD, + GRO, + PDB, + PSF, + TRR, + XTC, + LAMMPS_chain, + LAMMPSDUMP_chain1, + LAMMPSDUMP_chain2, + PDB_closed, + PDB_small, +) from MDAnalysisTests.util import no_warning @@ -44,22 +53,28 @@ class TestChainReader(object): @pytest.fixture() def universe(self): - return mda.Universe(PSF, - [DCD, CRD, DCD, CRD, DCD, CRD, CRD]) + return mda.Universe(PSF, [DCD, CRD, DCD, CRD, DCD, CRD, CRD]) @pytest.fixture() def transformed(ref): - return mda.Universe(PSF, - [DCD, CRD, DCD, CRD, DCD, CRD, CRD], - transformations=[translate([10,10,10])]) + return mda.Universe( + PSF, + [DCD, CRD, DCD, CRD, DCD, CRD, CRD], + transformations=[translate([10, 10, 10])], + ) def test_regular_repr(self): u = mda.Universe(PSF, [DCD, CRD, DCD]) - assert_equal("", u.trajectory.__repr__()) - + assert_equal( + "", + u.trajectory.__repr__(), + ) def test_truncated_repr(self, universe): - assert_equal("", universe.trajectory.__repr__()) + assert_equal( + "", + universe.trajectory.__repr__(), + ) def test_next_trajectory(self, universe): universe.trajectory.rewind() @@ -67,26 +82,34 @@ 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(universe.trajectory.n_frames, 3 * 98 + 4, - "wrong number of frames in chained dcd") + assert_equal( + universe.trajectory.n_frames, + 3 * 98 + 4, + "wrong number of frames in chained dcd", + ) def test_iteration(self, universe): for ts in universe.trajectory: pass # just forward to last frame - assert_equal(universe.trajectory.n_frames - 1, ts.frame, - "iteration yielded wrong number of frames ({0:d}), " - "should be {1:d}".format(ts.frame, - universe.trajectory.n_frames)) + assert_equal( + universe.trajectory.n_frames - 1, + ts.frame, + "iteration yielded wrong number of frames ({0:d}), " + "should be {1:d}".format(ts.frame, universe.trajectory.n_frames), + ) def test_jump_lastframe_trajectory(self, universe): universe.trajectory[-1] - assert_equal(universe.trajectory.ts.frame + 1, - universe.trajectory.n_frames, - "indexing last frame with trajectory[-1]") + assert_equal( + universe.trajectory.ts.frame + 1, + universe.trajectory.n_frames, + "indexing last frame with trajectory[-1]", + ) def test_slice_trajectory(self, universe): frames = [ts.frame for ts in universe.trajectory[5:17:3]] @@ -112,13 +135,17 @@ def test_frame(self, universe): # forward to frame where we repeat original dcd again: # dcd:0..97 crd:98 dcd:99..196 universe.trajectory[99] - assert_equal(universe.atoms.positions, coord0, - "coordinates at frame 1 and 100 should be the same!") + assert_equal( + universe.atoms.positions, + coord0, + "coordinates at frame 1 and 100 should be the same!", + ) def test_time(self, universe): universe.trajectory[30] # index and frames 0-based assert_almost_equal( - universe.trajectory.time, 30.0, 5, err_msg="Wrong time of frame") + universe.trajectory.time, 30.0, 5, err_msg="Wrong time of frame" + ) def test_write_dcd(self, universe, tmpdir): """test that ChainReader written dcd (containing crds) is correct @@ -129,53 +156,63 @@ def test_write_dcd(self, universe, tmpdir): W.write(universe) universe.trajectory.rewind() u = mda.Universe(PSF, outfile) - for (ts_orig, ts_new) in zip(universe.trajectory, u.trajectory): + for ts_orig, ts_new in zip(universe.trajectory, u.trajectory): assert_almost_equal( ts_orig._pos, ts_new._pos, self.prec, err_msg="Coordinates disagree at frame {0:d}".format( - ts_orig.frame)) + ts_orig.frame + ), + ) def test_transform_iteration(self, universe, transformed): - vector = np.float32([10,10,10]) + vector = np.float32([10, 10, 10]) # # Are the transformations applied and # are the coordinates "overtransformed"? # iterate once: for ts in transformed.trajectory: frame = ts.frame ref = universe.trajectory[frame].positions + vector - assert_almost_equal(ts.positions, ref, decimal = 6) + assert_almost_equal(ts.positions, ref, decimal=6) # iterate again: for ts in transformed.trajectory: frame = ts.frame ref = universe.trajectory[frame].positions + vector - assert_almost_equal(ts.positions, ref, decimal = 6) + assert_almost_equal(ts.positions, ref, decimal=6) def test_transform_slice(self, universe, transformed): - vector = np.float32([10,10,10]) + vector = np.float32([10, 10, 10]) # what happens when we slice the trajectory? for ts in transformed.trajectory[5:17:3]: frame = ts.frame ref = universe.trajectory[frame].positions + vector - assert_almost_equal(ts.positions, ref, decimal = 6) + assert_almost_equal(ts.positions, ref, decimal=6) def test_transform_switch(self, universe, transformed): - vector = np.float32([10,10,10]) + 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]) + 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): @@ -185,7 +222,8 @@ class TestChainReaderCommonDt(object): @pytest.fixture() def trajectory(self): universe = mda.Universe( - PSF, [DCD, CRD, DCD, CRD, DCD, CRD, CRD], dt=self.common_dt) + PSF, [DCD, CRD, DCD, CRD, DCD, CRD, CRD], dt=self.common_dt + ) return universe.trajectory def test_time(self, trajectory): @@ -196,56 +234,66 @@ def test_time(self, trajectory): trajectory.time, trajectory.frame * self.common_dt, 5, - err_msg="Wrong time for frame {0:d}".format(frame_n)) + err_msg="Wrong time for frame {0:d}".format(frame_n), + ) 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]) def test_set_all_format_lammps(self): universe = mda.Universe( - LAMMPS_chain, [LAMMPSDUMP_chain1, LAMMPSDUMP_chain2], - format="LAMMPSDUMP", continuous=True) + LAMMPS_chain, + [LAMMPSDUMP_chain1, LAMMPSDUMP_chain2], + format="LAMMPSDUMP", + continuous=True, + ) assert universe.trajectory.n_frames == 11 # Test whether the amount of time between frames is consistently = 1 time_values = np.array([ts.time for ts in universe.trajectory]) - dt_array = time_values[1:]-time_values[:-1] + dt_array = time_values[1:] - time_values[:-1] assert np.unique(dt_array) == 1 assert_equal(time_values, np.arange(11)) def test_set_format_tuples_and_format(self): - universe = mda.Universe(GRO, [(PDB, 'pdb'), GRO, GRO, (XTC, 'xtc'), - (TRR, 'trr')], format='gro') + universe = mda.Universe( + GRO, + [(PDB, "pdb"), GRO, GRO, (XTC, "xtc"), (TRR, "trr")], + format="gro", + ) assert universe.trajectory.n_frames == 23 assert_equal(universe.trajectory.filenames, [PDB, GRO, GRO, XTC, TRR]) with pytest.raises(TypeError) as errinfo: - mda.Universe(GRO, [(PDB, 'pdb'), GRO, GRO, (XTC, 'xtc'), - (TRR, 'trr')], format='pdb') - assert 'Unable to read' in str(errinfo.value) - + mda.Universe( + GRO, + [(PDB, "pdb"), GRO, GRO, (XTC, "xtc"), (TRR, "trr")], + format="pdb", + ) + assert "Unable to read" in str(errinfo.value) def test_set_one_format_tuple(self): - universe = mda.Universe(PSF, [(PDB_small, 'pdb'), DCD]) + universe = mda.Universe(PSF, [(PDB_small, "pdb"), DCD]) assert universe.trajectory.n_frames == 99 def test_set_all_formats(self): with pytest.raises(TypeError) as errinfo: - mda.Universe(PDB, [PDB, GRO], format='gro') - assert 'Unable to read' in str(errinfo.value) + mda.Universe(PDB, [PDB, GRO], format="gro") + assert "Unable to read" in str(errinfo.value) - universe = mda.Universe(GRO, [PDB, PDB, PDB], format='pdb') + universe = mda.Universe(GRO, [PDB, PDB, PDB], format="pdb") assert_equal(universe.trajectory.filenames, [PDB, PDB, PDB]) -def build_trajectories(folder, sequences, fmt='xtc'): +def build_trajectories(folder, sequences, fmt="xtc"): """ A scenario is given as a series of time sequences. The result is returned as a list of time and origin of the frame. Each element of that @@ -257,7 +305,7 @@ def build_trajectories(folder, sequences, fmt='xtc'): https://gist.github.com/jbarnoud/cacd0957d3df01d1577f640b20e86039 """ - template = 'trjcat_test_{{}}.{}'.format(fmt) + template = "trjcat_test_{{}}.{}".format(fmt) template = os.path.join(folder, template) # Use an empty universe to have a topology @@ -288,38 +336,63 @@ def __init__(self, seq, n_frames, order): self.n_frames = n_frames self.order = order - @pytest.mark.parametrize('fmt', ('xtc', 'trr')) - @pytest.mark.parametrize('seq_info',[ - SequenceInfo(seq=([0, 1, 2, 3], [2, 3, 4, 5], [4, 5, 6, 7]), - n_frames=8, - order=[0, 0, 1, 1, 2, 2, 2, 2]), - SequenceInfo(seq=([0, 1, 2, 4], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), - n_frames=10, - order=np.ones(10)), - SequenceInfo(seq=([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3]), - n_frames=4, - order=np.ones(4)), - SequenceInfo(seq=([5, 6, 7, 8, 9], [2, 3, 4, 5, 6], [0, 1, 2, 3]), - n_frames=10, - order=[2, 2, 1, 1, 1, 0, 0, 0, 0, 0]), - SequenceInfo(seq=([0, 1, 2],) * 3, - n_frames=3, - order=[2, 2, 2]), - SequenceInfo(seq=([0, 1, 2, 3,], [3, 4], [4, 5, 6, 7]), - n_frames=8, - order=[0, 0, 0, 1, 2, 2, 2, 2]), - SequenceInfo(seq=([5, 6, 7, 8, 9], [2, 3, 4, 5, 6], [0, 1, 2, 3]), - n_frames=10, - order=[2, 2, 1, 1, 1, 0, 0, 0, 0, 0]), - SequenceInfo(seq=[list(range(0, 6)), list(range(2, 5)), - list(range(2, 5)), list(range(2, 5)), - list(range(3, 8))], - n_frames=8, - order=[0, 0, 3, 4, 4, 4, 4, 4]), - ]) + @pytest.mark.parametrize("fmt", ("xtc", "trr")) + @pytest.mark.parametrize( + "seq_info", + [ + SequenceInfo( + seq=([0, 1, 2, 3], [2, 3, 4, 5], [4, 5, 6, 7]), + n_frames=8, + order=[0, 0, 1, 1, 2, 2, 2, 2], + ), + SequenceInfo( + seq=([0, 1, 2, 4], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), + n_frames=10, + order=np.ones(10), + ), + SequenceInfo( + seq=([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3]), + n_frames=4, + order=np.ones(4), + ), + SequenceInfo( + seq=([5, 6, 7, 8, 9], [2, 3, 4, 5, 6], [0, 1, 2, 3]), + n_frames=10, + order=[2, 2, 1, 1, 1, 0, 0, 0, 0, 0], + ), + SequenceInfo(seq=([0, 1, 2],) * 3, n_frames=3, order=[2, 2, 2]), + SequenceInfo( + seq=( + [0, 1, 2, 3], + [3, 4], + [4, 5, 6, 7], + ), + n_frames=8, + order=[0, 0, 0, 1, 2, 2, 2, 2], + ), + SequenceInfo( + seq=([5, 6, 7, 8, 9], [2, 3, 4, 5, 6], [0, 1, 2, 3]), + n_frames=10, + order=[2, 2, 1, 1, 1, 0, 0, 0, 0, 0], + ), + SequenceInfo( + seq=[ + list(range(0, 6)), + list(range(2, 5)), + list(range(2, 5)), + list(range(2, 5)), + list(range(3, 8)), + ], + n_frames=8, + order=[0, 0, 3, 4, 4, 4, 4, 4], + ), + ], + ) 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): @@ -330,14 +403,20 @@ def test_order(self, seq_info, tmpdir, fmt): def test_start_frames(self, tmpdir): folder = str(tmpdir) sequences = ([0, 1, 2, 3], [2, 3, 4, 5], [4, 5, 6, 7]) - utop, fnames = build_trajectories(folder, sequences=sequences,) + utop, fnames = build_trajectories( + folder, + sequences=sequences, + ) u = mda.Universe(utop._topology, fnames, continuous=True, to_guess=()) assert_equal(u.trajectory._start_frames, [0, 2, 4]) def test_missing(self, tmpdir): folder = str(tmpdir) sequences = ([0, 1, 2, 3], [5, 6, 7, 8, 9]) - utop, fnames = build_trajectories(folder, sequences=sequences,) + utop, fnames = build_trajectories( + folder, + sequences=sequences, + ) u = mda.Universe(utop._topology, fnames, continuous=True, to_guess=()) assert u.trajectory.n_frames == 9 @@ -345,7 +424,10 @@ def test_warning(self, tmpdir): folder = str(tmpdir) # this sequence *should* trigger a warning sequences = ([0, 1, 2, 3], [5, 6, 7]) - utop, fnames = build_trajectories(folder, sequences=sequences,) + utop, fnames = build_trajectories( + folder, + sequences=sequences, + ) with pytest.warns(UserWarning): mda.Universe(utop._topology, fnames, continuous=True, to_guess=()) @@ -353,7 +435,10 @@ def test_interleaving_error(self, tmpdir): folder = str(tmpdir) # interleaving is not supported by chainreader sequences = ([0, 2, 4, 6], [1, 3, 5, 7]) - utop, fnames = build_trajectories(folder, sequences=sequences,) + utop, fnames = build_trajectories( + folder, + sequences=sequences, + ) with pytest.raises(RuntimeError): mda.Universe(utop._topology, fnames, continuous=True, to_guess=()) @@ -361,7 +446,10 @@ def test_easy_trigger_warning(self, tmpdir): folder = str(tmpdir) # this sequence shouldn't trigger a warning sequences = ([0, 1, 2, 3], [2, 3, 4, 5], [4, 5, 6, 7]) - utop, fnames = build_trajectories(folder, sequences=sequences,) + utop, fnames = build_trajectories( + folder, + sequences=sequences, + ) with no_warning(UserWarning): with warnings.catch_warnings(): # for windows Python 3.10 ignore: @@ -370,14 +458,24 @@ def test_easy_trigger_warning(self, tmpdir): # 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=()) + action="ignore", category=ImportWarning + ) + mda.Universe( + utop._topology, fnames, continuous=True, to_guess=() + ) def test_single_frames(self, tmpdir): folder = str(tmpdir) - sequences = ([0, 1, 2, 3], [5, ]) - utop, fnames = build_trajectories(folder, sequences=sequences,) + sequences = ( + [0, 1, 2, 3], + [ + 5, + ], + ) + utop, fnames = build_trajectories( + folder, + sequences=sequences, + ) with pytest.raises(RuntimeError): mda.Universe(utop._topology, fnames, continuous=True, to_guess=()) @@ -396,33 +494,41 @@ def test_unsupported_filetypes(self): mda.Universe(PDB, [PDB, XTC], continuous=True) -@pytest.mark.parametrize('l, ref', ([((0, 3), (3, 3), (4, 7)), (0, 1, 2)], - [((0, 9), (0, 4)), (0, 1)], - [((0, 3), (2, 2), (3, 3), (2, 6), (5, 9)), (0, 1, 3, 2, 4)], - [((0, 2), (4, 9), (0, 4), (7, 9)), (0, 2, 1, 3)], - [((0, 5), (2, 4), (2, 4), (2, 4), (3, 7)), (0, 1, 2, 3, 4)] - )) +@pytest.mark.parametrize( + "l, ref", + ( + [((0, 3), (3, 3), (4, 7)), (0, 1, 2)], + [((0, 9), (0, 4)), (0, 1)], + [((0, 3), (2, 2), (3, 3), (2, 6), (5, 9)), (0, 1, 3, 2, 4)], + [((0, 2), (4, 9), (0, 4), (7, 9)), (0, 2, 1, 3)], + [((0, 5), (2, 4), (2, 4), (2, 4), (3, 7)), (0, 1, 2, 3, 4)], + ), +) def test_multilevel_arg_sort(l, ref): indices = mda.coordinates.chain.multi_level_argsort(l) assert_equal(indices, ref) -@pytest.mark.parametrize('l, ref', ([((0, 4), (3, 6), (6, 9)), (0, 1, 2)], - [((0, 3), (3, 4), (4, 7)), (0, 1, 2)], - [((0, 3), (3, 5), (4, 7)), (0, 1, 2)], - [((0, 3), (0, 4), (3, 5), (4, 7)), (1, 2, 3)], - [((0, 3), (0, 4)), (1,)], - [((0, 3), (0, 3)), (1,)], - [((1, 3), (0, 4)), (0,)], - [((0, 3), ), (0, )], - [((0, 3), (5, 9)), (0, 1)], - [((0, 3), (0, 3), (5, 9)), (1, 2)], - [((0, 3), (0, 3), (0, 3), (5, 9)), (2, 3)], - [((0, 5), (2, 4), (2, 4), (2, 4), (3, 7)), (0, 3, 4)], - [((0, 3), (2, 4), (2, 4), (2, 4), (3, 7)), (0, 3, 4)], - [((0, 3), (2, 4), (4, 7), (4, 7), (4, 7), (6, 9)), (0, 1, 4, 5)], - [((0, 6), (2, 5), (2, 5), (2, 5), (3, 8)), (0, 3, 4)], - )) +@pytest.mark.parametrize( + "l, ref", + ( + [((0, 4), (3, 6), (6, 9)), (0, 1, 2)], + [((0, 3), (3, 4), (4, 7)), (0, 1, 2)], + [((0, 3), (3, 5), (4, 7)), (0, 1, 2)], + [((0, 3), (0, 4), (3, 5), (4, 7)), (1, 2, 3)], + [((0, 3), (0, 4)), (1,)], + [((0, 3), (0, 3)), (1,)], + [((1, 3), (0, 4)), (0,)], + [((0, 3),), (0,)], + [((0, 3), (5, 9)), (0, 1)], + [((0, 3), (0, 3), (5, 9)), (1, 2)], + [((0, 3), (0, 3), (0, 3), (5, 9)), (2, 3)], + [((0, 5), (2, 4), (2, 4), (2, 4), (3, 7)), (0, 3, 4)], + [((0, 3), (2, 4), (2, 4), (2, 4), (3, 7)), (0, 3, 4)], + [((0, 3), (2, 4), (4, 7), (4, 7), (4, 7), (6, 9)), (0, 1, 4, 5)], + [((0, 6), (2, 5), (2, 5), (2, 5), (3, 8)), (0, 3, 4)], + ), +) def test_filter_times(l, ref): indices = mda.coordinates.chain.filter_times(l, dt=1) assert_equal(indices, ref) @@ -466,11 +572,15 @@ def test_issue_3349(): u_expected_filenames = np.array([None, str(DCD)]) u2_expected_filenames = np.array([None, None, None, str(DCD)]) - assert_equal("", - u.trajectory.__repr__()) + assert_equal( + "", + u.trajectory.__repr__(), + ) assert_equal(u_expected_filenames, u.trajectory.filenames) - assert_equal("", - u2.trajectory.__repr__()) + assert_equal( + "", + u2.trajectory.__repr__(), + ) assert_equal(u2_expected_filenames, u2.trajectory.filenames) diff --git a/testsuite/MDAnalysisTests/coordinates/test_chemfiles.py b/testsuite/MDAnalysisTests/coordinates/test_chemfiles.py index fd489977fe..a556414de3 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_chemfiles.py +++ b/testsuite/MDAnalysisTests/coordinates/test_chemfiles.py @@ -54,7 +54,9 @@ 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 @@ -97,7 +99,9 @@ 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() @@ -142,7 +146,9 @@ 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() @@ -159,7 +165,9 @@ 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( @@ -183,7 +191,9 @@ 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() @@ -194,7 +204,9 @@ 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 91fb87fd46..6a6cd86590 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_copying.py +++ b/testsuite/MDAnalysisTests/coordinates/test_copying.py @@ -21,6 +21,7 @@ # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # import numpy as np + try: from numpy import shares_memory except ImportError: @@ -64,39 +65,41 @@ from MDAnalysis.auxiliary.EDR import HAS_PYEDR -@pytest.fixture(params=[ - # formatname, filename - ('CRD', CRD, dict()), - ('DATA', LAMMPSdata_mini, dict(n_atoms=1)), - ('DCD', DCD, dict()), - ('DMS', DMS, dict()), - ('CONFIG', DLP_CONFIG, dict()), - ('HISTORY', DLP_HISTORY, dict()), - ('INPCRD', INPCRD, dict()), - ('GMS', GMS_ASYMOPT, dict()), - ('GRO', GRO, dict()), - ('MMTF', MMTF, dict()), - ('MOL2', mol2_molecules, dict()), - ('PDB', PDB_small, dict()), - ('PQR', PQR, dict()), - ('PDBQT', PDBQT_input, dict()), - ('TRR', TRR, dict()), - ('TRZ', TRZ, dict(n_atoms=8184)), - ('TRJ', TRJ, dict(n_atoms=252)), - ('XTC', XTC, dict()), - ('XPDB', XPDB_small, dict()), - ('XYZ', XYZ_mini, dict()), - ('NCDF', NCDF, dict()), - ('memory', np.arange(60).reshape(2, 10, 3).astype(np.float64), dict()), - ('CHAIN', [GRO, GRO, GRO], dict()), - ('FHIAIMS', FHIAIMS, dict()), - pytest.param( - ('GSD', GSD, dict()), - marks=pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') - ), - ('NAMDBIN', NAMDBIN, dict()), - ('TXYZ', TXYZ, dict()), -]) +@pytest.fixture( + params=[ + # formatname, filename + ("CRD", CRD, dict()), + ("DATA", LAMMPSdata_mini, dict(n_atoms=1)), + ("DCD", DCD, dict()), + ("DMS", DMS, dict()), + ("CONFIG", DLP_CONFIG, dict()), + ("HISTORY", DLP_HISTORY, dict()), + ("INPCRD", INPCRD, dict()), + ("GMS", GMS_ASYMOPT, dict()), + ("GRO", GRO, dict()), + ("MMTF", MMTF, dict()), + ("MOL2", mol2_molecules, dict()), + ("PDB", PDB_small, dict()), + ("PQR", PQR, dict()), + ("PDBQT", PDBQT_input, dict()), + ("TRR", TRR, dict()), + ("TRZ", TRZ, dict(n_atoms=8184)), + ("TRJ", TRJ, dict(n_atoms=252)), + ("XTC", XTC, dict()), + ("XPDB", XPDB_small, dict()), + ("XYZ", XYZ_mini, dict()), + ("NCDF", NCDF, dict()), + ("memory", np.arange(60).reshape(2, 10, 3).astype(np.float64), dict()), + ("CHAIN", [GRO, GRO, GRO], dict()), + ("FHIAIMS", FHIAIMS, dict()), + pytest.param( + ("GSD", GSD, dict()), + marks=pytest.mark.skipif(not HAS_GSD, reason="gsd not installed"), + ), + ("NAMDBIN", NAMDBIN, dict()), + ("TXYZ", TXYZ, dict()), + ] +) def ref_reader(request): fmt_name, filename, extras = request.param @@ -108,45 +111,52 @@ def ref_reader(request): r.close() -@pytest.fixture(params=[ - # formatname, filename - ('CRD', CRD, dict()), - ('DATA', LAMMPSdata_mini, dict(n_atoms=1)), - ('DCD', DCD, dict()), - ('DMS', DMS, dict()), - ('CONFIG', DLP_CONFIG, dict()), - ('HISTORY', DLP_HISTORY, dict()), - ('INPCRD', INPCRD, dict()), - ('GMS', GMS_ASYMOPT, dict()), - ('GRO', GRO, dict()), - ('MMTF', MMTF, dict()), - ('MOL2', mol2_molecules, dict()), - ('PDB', PDB_small, dict()), - ('PQR', PQR, dict()), - ('PDBQT', PDBQT_input, dict()), - ('TRR', TRR, dict()), - ('TRZ', TRZ, dict(n_atoms=8184)), - ('TRJ', TRJ, dict(n_atoms=252)), - ('XTC', XTC, dict()), - ('XPDB', XPDB_small, dict()), - ('XYZ', XYZ_mini, dict()), - ('NCDF', NCDF, dict(mmap=False)), - ('memory', np.arange(60).reshape(2, 10, 3).astype(np.float64), dict()), - ('CHAIN', [GRO, GRO, GRO], dict()), - ('FHIAIMS', FHIAIMS, dict()), - pytest.param( - ('GSD', GSD, dict()), - marks=pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') - ), - ('NAMDBIN', NAMDBIN, dict()), - ('TXYZ', TXYZ, dict()), -]) +@pytest.fixture( + params=[ + # formatname, filename + ("CRD", CRD, dict()), + ("DATA", LAMMPSdata_mini, dict(n_atoms=1)), + ("DCD", DCD, dict()), + ("DMS", DMS, dict()), + ("CONFIG", DLP_CONFIG, dict()), + ("HISTORY", DLP_HISTORY, dict()), + ("INPCRD", INPCRD, dict()), + ("GMS", GMS_ASYMOPT, dict()), + ("GRO", GRO, dict()), + ("MMTF", MMTF, dict()), + ("MOL2", mol2_molecules, dict()), + ("PDB", PDB_small, dict()), + ("PQR", PQR, dict()), + ("PDBQT", PDBQT_input, dict()), + ("TRR", TRR, dict()), + ("TRZ", TRZ, dict(n_atoms=8184)), + ("TRJ", TRJ, dict(n_atoms=252)), + ("XTC", XTC, dict()), + ("XPDB", XPDB_small, dict()), + ("XYZ", XYZ_mini, dict()), + ("NCDF", NCDF, dict(mmap=False)), + ("memory", np.arange(60).reshape(2, 10, 3).astype(np.float64), dict()), + ("CHAIN", [GRO, GRO, GRO], dict()), + ("FHIAIMS", FHIAIMS, dict()), + pytest.param( + ("GSD", GSD, dict()), + marks=pytest.mark.skipif(not HAS_GSD, reason="gsd not installed"), + ), + ("NAMDBIN", NAMDBIN, dict()), + ("TXYZ", TXYZ, dict()), + ] +) def ref_reader_extra_args(request): fmt_name, filename, extras = request.param r = get_reader_for(filename, format=fmt_name)( - filename, convert_units=False, dt=2, time_offset=10, - foo="bar", **extras) + filename, + convert_units=False, + dt=2, + time_offset=10, + foo="bar", + **extras, + ) try: yield r finally: @@ -189,23 +199,23 @@ def test_reader_copied_extra_attributes(original_and_copy_extra_args): # memory reader subclass protoreader directly and # therefore don't have convert_units or _ts_kwargs if original.__class__.__bases__[0].__name__ != "ProtoReader": - assert original.format is not 'MEMORY' + assert original.format is not "MEMORY" assert original.convert_units is False assert copy.convert_units is False - assert original._ts_kwargs['time_offset'] == 10 - assert copy._ts_kwargs['time_offset'] == 10 - assert original._ts_kwargs['dt'] == 2 - assert copy._ts_kwargs['dt'] == 2 + assert original._ts_kwargs["time_offset"] == 10 + assert copy._ts_kwargs["time_offset"] == 10 + assert original._ts_kwargs["dt"] == 2 + assert copy._ts_kwargs["dt"] == 2 - assert original.ts.data['time_offset'] == 10 - assert copy.ts.data['time_offset'] == 10 + assert original.ts.data["time_offset"] == 10 + assert copy.ts.data["time_offset"] == 10 # Issue #3689 XTC and XDR overwrite `dt` - if original.format not in ('XTC', 'TRR'): - assert original.ts.data['dt'] == 2 - assert copy.ts.data['dt'] == 2 + if original.format not in ("XTC", "TRR"): + assert original.ts.data["dt"] == 2 + assert copy.ts.data["dt"] == 2 - assert copy._kwargs['foo'] == 'bar' + assert copy._kwargs["foo"] == "bar" # checking that non-base attributes are also copied (netcdf reader) if hasattr(original, "_mmap"): @@ -217,7 +227,7 @@ def test_reader_independent_iteration(original_and_copy): # check that the two Readers iterate independently original, copy = original_and_copy if len(original) < 2: - pytest.skip('Single frame reader') + pytest.skip("Single frame reader") # initially at same frame assert original.ts.frame == copy.ts.frame @@ -231,7 +241,7 @@ def test_reader_initial_frame_maintained(original_and_copy): original, _ = original_and_copy if len(original) < 2: - pytest.skip('Single frame reader') + pytest.skip("Single frame reader") # seek original[1] @@ -241,6 +251,7 @@ def test_reader_initial_frame_maintained(original_and_copy): assert original.ts.frame == copy.ts.frame assert_equal(original.ts.positions, copy.ts.positions) + def test_reader_initial_next(original_and_copy): # check that the filehandle (or equivalent) in the copied Reader # is identical to the original @@ -248,7 +259,7 @@ def test_reader_initial_next(original_and_copy): original, _ = original_and_copy if len(original) < 3: - pytest.skip('Requires 3 frames') + pytest.skip("Requires 3 frames") original[1] @@ -259,7 +270,7 @@ def test_reader_initial_next(original_and_copy): original.next() copy.next() - + assert original.ts.frame == copy.ts.frame assert_equal(original.ts.positions, copy.ts.positions) @@ -277,8 +288,9 @@ 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 cffde92d75..be68d82eae 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_crd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_crd.py @@ -23,9 +23,7 @@ from collections import OrderedDict import pytest -from numpy.testing import ( - assert_equal,assert_allclose -) +from numpy.testing import assert_equal, assert_allclose import MDAnalysis as mda import os @@ -41,10 +39,11 @@ def u(self): @pytest.fixture() def outfile(self, tmpdir): - return os.path.join(str(tmpdir), 'test.crd') + 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(): @@ -52,8 +51,7 @@ def test_write_atoms(self, u, testfile, tmpdir): u2 = mda.Universe(testfile) - assert_equal(u.atoms.positions, - u2.atoms.positions) + assert_equal(u.atoms.positions, u2.atoms.positions) def test_roundtrip(self, u, outfile): # Write out a copy of the Universe, and compare this against the original @@ -62,9 +60,9 @@ def test_roundtrip(self, u, outfile): u.atoms.write(outfile) def CRD_iter(fn): - with open(fn, 'r') as inf: + with open(fn, "r") as inf: for line in inf: - if not line.startswith('*'): + if not line.startswith("*"): yield line for ref, other in zip(CRD_iter(CRD), CRD_iter(outfile)): @@ -74,9 +72,9 @@ def test_write_EXT(self, u, outfile): # Use the `extended` keyword to force the EXT format u.atoms.write(outfile, extended=True) - with open(outfile, 'r') as inf: + with open(outfile, "r") as inf: format_line = inf.readlines()[2] - assert 'EXT' in format_line, "EXT format expected" + assert "EXT" in format_line, "EXT format expected" def test_write_EXT_read(self, u, outfile): # Read EXT format and check atom positions @@ -84,56 +82,61 @@ def test_write_EXT_read(self, u, outfile): u2 = mda.Universe(outfile) - sel1 = u.select_atoms('all') - sel2 = u2.select_atoms('all') + sel1 = u.select_atoms("all") + sel2 = u2.select_atoms("all") cog1 = sel1.center_of_geometry() cog2 = sel2.center_of_geometry() - assert_equal(len(u.atoms), len(u2.atoms)), 'Equal number of '\ - 'atoms expected in both CRD formats' - assert_equal(len(u.atoms.residues), - len(u2.atoms.residues)), 'Equal number of residues expected in'\ - 'both CRD formats' - assert_equal(len(u.atoms.segments), - len(u2.atoms.segments)), 'Equal number of segments expected in'\ - 'both CRD formats' - assert_allclose(cog1, cog2, rtol=1e-6, atol=0), 'Same centroid expected for both CRD formats' + assert_equal( + len(u.atoms), len(u2.atoms) + ), "Equal number of " "atoms expected in both CRD formats" + assert_equal( + len(u.atoms.residues), len(u2.atoms.residues) + ), "Equal number of residues expected in" "both CRD formats" + assert_equal( + len(u.atoms.segments), len(u2.atoms.segments) + ), "Equal number of segments expected in" "both CRD formats" + assert_allclose( + cog1, cog2, rtol=1e-6, atol=0 + ), "Same centroid expected for both CRD formats" class TestCRDWriterMissingAttrs(object): # All required attributes with the default value - req_attrs = OrderedDict([ - ('resnames', 'UNK'), - ('resids', 1), - ('names', 'X'), - ('tempfactors', 0.0), - ]) - - @pytest.mark.parametrize('missing_attr', req_attrs) + req_attrs = OrderedDict( + [ + ("resnames", "UNK"), + ("resids", 1), + ("names", "X"), + ("tempfactors", 0.0), + ] + ) + + @pytest.mark.parametrize("missing_attr", req_attrs) def test_warns(self, missing_attr, tmpdir): attrs = list(self.req_attrs.keys()) attrs.remove(missing_attr) u = make_Universe(attrs, trajectory=True) - outfile = str(tmpdir) + '/out.crd' + outfile = str(tmpdir) + "/out.crd" with pytest.warns(UserWarning): u.atoms.write(outfile) - @pytest.mark.parametrize('missing_attr', req_attrs) + @pytest.mark.parametrize("missing_attr", req_attrs) def test_write(self, missing_attr, tmpdir): attrs = list(self.req_attrs.keys()) attrs.remove(missing_attr) u = make_Universe(attrs, trajectory=True) - outfile = str(tmpdir) + '/out.crd' + outfile = str(tmpdir) + "/out.crd" u.atoms.write(outfile) u2 = mda.Universe(outfile) # Check all other attrs aren't disturbed for attr in attrs: - assert_equal(getattr(u.atoms, attr), - getattr(u2.atoms, attr)) + 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 9d27f8163f..32dadddd96 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_dcd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_dcd.py @@ -27,18 +27,34 @@ import MDAnalysis as mda from MDAnalysis.coordinates.DCD import DCDReader -from numpy.testing import (assert_equal, assert_array_equal, - assert_almost_equal, assert_array_almost_equal) - -from MDAnalysisTests.datafiles import (DCD, PSF, DCD_empty, PRMncdf, NCDF, - COORDINATES_TOPOLOGY, COORDINATES_DCD, - PSF_TRICLINIC, DCD_TRICLINIC, - PSF_NAMD_TRICLINIC, DCD_NAMD_TRICLINIC, - PSF_NAMD_GBIS, DCD_NAMD_GBIS, - PDB_closed) -from MDAnalysisTests.coordinates.base import (MultiframeReaderTest, - BaseReference, - BaseWriterTest) +from numpy.testing import ( + assert_equal, + assert_array_equal, + assert_almost_equal, + assert_array_almost_equal, +) + +from MDAnalysisTests.datafiles import ( + DCD, + PSF, + DCD_empty, + PRMncdf, + NCDF, + COORDINATES_TOPOLOGY, + COORDINATES_DCD, + PSF_TRICLINIC, + DCD_TRICLINIC, + PSF_NAMD_TRICLINIC, + DCD_NAMD_TRICLINIC, + PSF_NAMD_GBIS, + DCD_NAMD_GBIS, + PDB_closed, +) +from MDAnalysisTests.coordinates.base import ( + MultiframeReaderTest, + BaseReference, + BaseWriterTest, +) import pytest @@ -50,7 +66,7 @@ def __init__(self): self.topology = COORDINATES_TOPOLOGY self.reader = mda.coordinates.DCD.DCDReader self.writer = mda.coordinates.DCD.DCDWriter - self.ext = 'xtc' + self.ext = "xtc" self.prec = 3 self.changing_dimensions = True @@ -76,37 +92,47 @@ def test_with_statement(self): assert_equal( N, 98, - err_msg="with_statement: DCDReader reads wrong number of frames") + err_msg="with_statement: DCDReader reads wrong number of frames", + ) assert_array_equal( frames, np.arange(0, N), - err_msg="with_statement: DCDReader does not read all frames") + err_msg="with_statement: DCDReader does not read all frames", + ) def test_set_time(self): u = mda.Universe(PSF, DCD) - assert_almost_equal(u.trajectory.time, 1.0, - decimal=5) + assert_almost_equal(u.trajectory.time, 1.0, decimal=5) -@pytest.mark.parametrize('fstart', (0, 1, 2, 37, None)) +@pytest.mark.parametrize("fstart", (0, 1, 2, 37, None)) def test_write_istart(universe_dcd, tmpdir, fstart): - outfile = str(tmpdir.join('test.dcd')) - nsavc = universe_dcd.trajectory._file.header['nsavc'] + outfile = str(tmpdir.join("test.dcd")) + nsavc = universe_dcd.trajectory._file.header["nsavc"] istart = fstart * nsavc if fstart is not None else None - with mda.Writer(outfile, universe_dcd.atoms.n_atoms, - nsavc=nsavc, istart=istart) as w: + with mda.Writer( + outfile, universe_dcd.atoms.n_atoms, nsavc=nsavc, istart=istart + ) as w: for ts in universe_dcd.trajectory: w.write(universe_dcd.atoms) u = mda.Universe(PSF, outfile) - assert_almost_equal(u.trajectory._file.header['istart'], - istart if istart is not None else u.trajectory._file.header['nsavc']) + assert_almost_equal( + u.trajectory._file.header["istart"], + istart if istart is not None else u.trajectory._file.header["nsavc"], + ) # issue #1819 times = [ts.time for ts in u.trajectory] fstart = fstart if fstart is not None else 1 - ref_times = (np.arange(universe_dcd.trajectory.n_frames) + fstart) * universe_dcd.trajectory.dt - assert_almost_equal(times, ref_times, decimal=5, - err_msg="Times not identical after setting istart={}".format(istart)) + ref_times = ( + np.arange(universe_dcd.trajectory.n_frames) + fstart + ) * universe_dcd.trajectory.dt + assert_almost_equal( + times, + ref_times, + decimal=5, + err_msg="Times not identical after setting istart={}".format(istart), + ) class TestDCDWriter(BaseWriterTest): @@ -117,10 +143,9 @@ def ref(): def test_write_random_unitcell(tmpdir): - testname = str(tmpdir.join('test.dcd')) + testname = str(tmpdir.join("test.dcd")) rstate = np.random.RandomState(1178083) - random_unitcells = rstate.uniform( - high=80, size=(98, 6)).astype(np.float64) + random_unitcells = rstate.uniform(high=80, size=(98, 6)).astype(np.float64) u = mda.Universe(PSF, DCD) with mda.Writer(testname, n_atoms=u.atoms.n_atoms) as w: @@ -130,15 +155,15 @@ def test_write_random_unitcell(tmpdir): u2 = mda.Universe(PSF, testname) for index, ts in enumerate(u2.trajectory): - assert_array_almost_equal(u2.trajectory.dimensions, - random_unitcells[index], - decimal=5) + assert_array_almost_equal( + u2.trajectory.dimensions, random_unitcells[index], decimal=5 + ) def test_empty_dimension_warning(tmpdir): u = mda.Universe(PDB_closed) - testname = str(tmpdir.join('test.dcd')) + testname = str(tmpdir.join("test.dcd")) with mda.Writer(testname, n_atoms=u.atoms.n_atoms) as w: msg = "zeroed unitcell will be written" @@ -150,7 +175,8 @@ def test_empty_dimension_warning(tmpdir): # Legacy tests # ################ -@pytest.fixture(scope='module') + +@pytest.fixture(scope="module") def universe_dcd(): return mda.Universe(PSF, DCD) @@ -171,8 +197,7 @@ def test_jump_last_frame(universe_dcd): assert universe_dcd.trajectory.ts.frame == 97 -@pytest.mark.parametrize("start, stop, step", ((5, 17, 3), - (20, 5, -1))) +@pytest.mark.parametrize("start, stop, step", ((5, 17, 3), (20, 5, -1))) def test_slice(universe_dcd, start, stop, step): frames = [ts.frame for ts in universe_dcd.trajectory[start:stop:step]] assert_array_equal(frames, np.arange(start, stop, step)) @@ -185,8 +210,9 @@ 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) @@ -194,41 +220,63 @@ def test_list_indices(universe_dcd, indices): @pytest.mark.parametrize( "slice, length", - [([None, None, None], 98), ([0, None, None], 98), ([None, 98, None], 98), - ([None, None, 1], 98), ([None, None, -1], 98), ([2, 6, 2], 2), - ([0, 10, None], 10), ([2, 10, None], 8), ([0, 1, 1], 1), ([1, 1, 1], 0), - ([1, 2, 1], 1), ([1, 2, 2], 1), ([1, 4, 2], 2), ([1, 4, 4], 1), - ([0, 5, 5], 1), ([3, 5, 1], 2), ([4, 0, -1], 4), ([5, 0, -2], 3), - ([5, 0, -4], 2)]) + [ + ([None, None, None], 98), + ([0, None, None], 98), + ([None, 98, None], 98), + ([None, None, 1], 98), + ([None, None, -1], 98), + ([2, 6, 2], 2), + ([0, 10, None], 10), + ([2, 10, None], 8), + ([0, 1, 1], 1), + ([1, 1, 1], 0), + ([1, 2, 1], 1), + ([1, 2, 2], 1), + ([1, 4, 2], 2), + ([1, 4, 4], 1), + ([0, 5, 5], 1), + ([3, 5, 1], 2), + ([4, 0, -1], 4), + ([5, 0, -2], 3), + ([5, 0, -4], 2), + ], +) def test_timeseries_slices(slice, length, universe_dcd): start, stop, step = slice - allframes = universe_dcd.trajectory.timeseries(order='fac') - xyz = universe_dcd.trajectory.timeseries(start=start, stop=stop, step=step, - order='fac') + allframes = universe_dcd.trajectory.timeseries(order="fac") + xyz = universe_dcd.trajectory.timeseries( + start=start, stop=stop, step=step, order="fac" + ) assert len(xyz) == length assert_array_almost_equal(xyz, allframes[start:stop:step]) -@pytest.mark.parametrize("order, shape", ( - ('fac', (98, 3341, 3)), - ('fca', (98, 3, 3341)), - ('afc', (3341, 98, 3)), - ('acf', (3341, 3, 98)), - ('caf', (3, 3341, 98)), - ('cfa', (3, 98, 3341)), )) +@pytest.mark.parametrize( + "order, shape", + ( + ("fac", (98, 3341, 3)), + ("fca", (98, 3, 3341)), + ("afc", (3341, 98, 3)), + ("acf", (3341, 3, 98)), + ("caf", (3, 3341, 98)), + ("cfa", (3, 98, 3341)), + ), +) def test_timeseries_order(order, shape, universe_dcd): x = universe_dcd.trajectory.timeseries(order=order) 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] - xyz = universe_dcd.trajectory.timeseries(asel=asel, order='afc') - assert len(xyz) == len(indices) - assert_array_almost_equal(xyz, allframes[indices]) + allframes = universe_dcd.trajectory.timeseries(order="afc") + asel = universe_dcd.atoms[indices] + xyz = universe_dcd.trajectory.timeseries(asel=asel, order="afc") + assert len(xyz) == len(indices) + assert_array_almost_equal(xyz, allframes[indices]) def test_reader_set_dt(): @@ -236,17 +284,19 @@ def test_reader_set_dt(): frame = 3 u = mda.Universe(PSF, DCD, dt=dt) dcdheader = u.trajectory._file.header - fstart = dcdheader['istart'] / dcdheader['nsavc'] - assert_almost_equal(u.trajectory[frame].time, (frame + fstart)*dt, - err_msg="setting time step dt={0} failed: " - "actually used dt={1}".format( - dt, u.trajectory._ts_kwargs['dt'])) - assert_almost_equal(u.trajectory.dt, dt, - err_msg="trajectory.dt does not match set dt") - - -@pytest.mark.parametrize("ext, decimal", (("dcd", 4), - ("xtc", 3))) + fstart = dcdheader["istart"] / dcdheader["nsavc"] + assert_almost_equal( + u.trajectory[frame].time, + (frame + fstart) * dt, + err_msg="setting time step dt={0} failed: " + "actually used dt={1}".format(dt, u.trajectory._ts_kwargs["dt"]), + ) + assert_almost_equal( + u.trajectory.dt, dt, err_msg="trajectory.dt does not match set dt" + ) + + +@pytest.mark.parametrize("ext, decimal", (("dcd", 4), ("xtc", 3))) def test_writer_dt(tmpdir, ext, decimal): dt = 5.0 # set time step to 5 ps universe_dcd = mda.Universe(PSF, DCD, dt=dt) @@ -259,13 +309,21 @@ def test_writer_dt(tmpdir, ext, decimal): W.write(universe_dcd.atoms) uw = mda.Universe(PSF, outfile) - assert_almost_equal(uw.trajectory.totaltime, - (uw.trajectory.n_frames - 1) * dt, decimal=decimal, - err_msg="Total time mismatch for ext={}".format(ext)) + assert_almost_equal( + uw.trajectory.totaltime, + (uw.trajectory.n_frames - 1) * dt, + decimal=decimal, + err_msg="Total time mismatch for ext={}".format(ext), + ) times = np.array([uw.trajectory.time for ts in uw.trajectory]) frames = np.arange(1, uw.trajectory.n_frames + 1) # traj starts at 1*dt - assert_array_almost_equal(times, frames * dt, decimal=decimal, - err_msg="Times mismatch for ext={}".format(ext)) + assert_array_almost_equal( + times, + frames * dt, + decimal=decimal, + err_msg="Times mismatch for ext={}".format(ext), + ) + @pytest.mark.parametrize("variable, default", (("istart", 0), ("nsavc", 1))) def test_DCDWriter_default(tmpdir, variable, default): @@ -277,8 +335,8 @@ def test_DCDWriter_default(tmpdir, variable, default): header = DCD.header assert header[variable] == default -@pytest.mark.parametrize("ext, decimal", (("dcd", 5), - ("xtc", 2))) + +@pytest.mark.parametrize("ext, decimal", (("dcd", 5), ("xtc", 2))) def test_other_writer(universe_dcd, tmpdir, ext, decimal): t = universe_dcd.trajectory outfile = str(tmpdir.join("test.{}".format(ext))) @@ -288,14 +346,17 @@ def test_other_writer(universe_dcd, tmpdir, ext, decimal): uw = mda.Universe(PSF, outfile) # check that the coordinates are identical for each time step - for orig_ts, written_ts in zip(universe_dcd.trajectory, - uw.trajectory): - assert_array_almost_equal(written_ts.positions, orig_ts.positions, - decimal, - err_msg="coordinate mismatch between " - "original and written trajectory at " - "frame {} (orig) vs {} (written)".format( - orig_ts.frame, written_ts.frame)) + for orig_ts, written_ts in zip(universe_dcd.trajectory, uw.trajectory): + assert_array_almost_equal( + written_ts.positions, + orig_ts.positions, + decimal, + err_msg="coordinate mismatch between " + "original and written trajectory at " + "frame {} (orig) vs {} (written)".format( + orig_ts.frame, written_ts.frame + ), + ) def test_single_frame(universe_dcd, tmpdir): @@ -305,15 +366,17 @@ def test_single_frame(universe_dcd, tmpdir): W.write(u.atoms) w = mda.Universe(PSF, outfile) assert w.trajectory.n_frames == 1 - assert_almost_equal(w.atoms.positions, - u.atoms.positions, - 3, - err_msg="coordinates do not match") + assert_almost_equal( + w.atoms.positions, + u.atoms.positions, + 3, + err_msg="coordinates do not match", + ) def test_write_no_natoms(): with pytest.raises(ValueError): - mda.Writer('foobar.dcd') + mda.Writer("foobar.dcd") def test_writer_trajectory_no_natoms(tmpdir, universe_dcd): @@ -326,18 +389,20 @@ class RefCHARMMtriclinicDCD(object): trajectory = DCD_TRICLINIC # time(ps) A B C alpha beta gamma (length in Angstrome, angles in degrees) # dcd starts at t = 1ps - ref_dimensions = np.array([ - [1., 35.44604, 35.06156, 34.1585, 91.32802, 61.73521, 44.40703], - [2., 34.65957, 34.22689, 33.09897, 90.56206, 61.79192, 44.14549], - [3., 34.52772, 34.66422, 33.53881, 90.55859, 63.11228, 40.14044], - [4., 34.43749, 33.38432, 34.02133, 88.82457, 64.98057, 36.77397], - [5., 33.73129, 32.47752, 34.18961, 89.88102, 65.89032, 36.10921], - [6., 33.78703, 31.90317, 34.98833, 90.03092, 66.12877, 35.07141], - [7., 33.24708, 31.18271, 34.9654, 93.11122, 68.17743, 35.73643], - [8., 32.92599, 30.31393, 34.99197, 93.89051, 69.3799, 33.48945], - [9., 32.15295, 30.43056, 34.96157, 96.01416, 71.50115, 32.56111], - [10., 31.99748, 30.21518, 35.24292, 95.85821, 71.08429, 31.85939] - ]) + ref_dimensions = np.array( + [ + [1.0, 35.44604, 35.06156, 34.1585, 91.32802, 61.73521, 44.40703], + [2.0, 34.65957, 34.22689, 33.09897, 90.56206, 61.79192, 44.14549], + [3.0, 34.52772, 34.66422, 33.53881, 90.55859, 63.11228, 40.14044], + [4.0, 34.43749, 33.38432, 34.02133, 88.82457, 64.98057, 36.77397], + [5.0, 33.73129, 32.47752, 34.18961, 89.88102, 65.89032, 36.10921], + [6.0, 33.78703, 31.90317, 34.98833, 90.03092, 66.12877, 35.07141], + [7.0, 33.24708, 31.18271, 34.9654, 93.11122, 68.17743, 35.73643], + [8.0, 32.92599, 30.31393, 34.99197, 93.89051, 69.3799, 33.48945], + [9.0, 32.15295, 30.43056, 34.96157, 96.01416, 71.50115, 32.56111], + [10.0, 31.99748, 30.21518, 35.24292, 95.85821, 71.08429, 31.85939], + ] + ) class RefNAMDtriclinicDCD(object): @@ -346,25 +411,39 @@ class RefNAMDtriclinicDCD(object): # vmd topology trajectory # molinfo 0 get {a b c alpha beta gamma} # time(ps) A B C alpha beta gamma (length in Angstrome, angles in degrees) - ref_dimensions = np.array([ - [1., 38.426594, 38.393101, 44.759800, 90.000000, 90.000000, 60.028915], - ]) + ref_dimensions = np.array( + [ + [ + 1.0, + 38.426594, + 38.393101, + 44.759800, + 90.000000, + 90.000000, + 60.028915, + ], + ] + ) @pytest.mark.parametrize("ref", (RefCHARMMtriclinicDCD, RefNAMDtriclinicDCD)) def test_read_unitcell_triclinic(ref): u = mda.Universe(ref.topology, ref.trajectory) for ts, box in zip(u.trajectory, ref.ref_dimensions[:, 1:]): - assert_array_almost_equal(ts.dimensions, box, 4, - err_msg="box dimensions A,B,C,alpha," - "beta,gamma not identical at frame " - "{}".format(ts.frame)) + assert_array_almost_equal( + ts.dimensions, + box, + 4, + err_msg="box dimensions A,B,C,alpha," + "beta,gamma not identical at frame " + "{}".format(ts.frame), + ) @pytest.mark.parametrize("ref", (RefCHARMMtriclinicDCD, RefNAMDtriclinicDCD)) def test_write_unitcell_triclinic(ref, tmpdir): u = mda.Universe(ref.topology, ref.trajectory) - outfile = 'triclinic.dcd' + outfile = "triclinic.dcd" with tmpdir.as_cwd(): with u.trajectory.OtherWriter(outfile) as w: for ts in u.trajectory: @@ -372,15 +451,19 @@ def test_write_unitcell_triclinic(ref, tmpdir): w = mda.Universe(ref.topology, outfile) for ts_orig, ts_copy in zip(u.trajectory, w.trajectory): - assert_almost_equal(ts_orig.dimensions, ts_copy.dimensions, 4, - err_msg="DCD->DCD: unit cell dimensions wrong " - "at frame {0}".format(ts_orig.frame)) + assert_almost_equal( + ts_orig.dimensions, + ts_copy.dimensions, + 4, + err_msg="DCD->DCD: unit cell dimensions wrong " + "at frame {0}".format(ts_orig.frame), + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def ncdf2dcd(tmpdir_factory): pytest.importorskip("netCDF4") - testfile = tmpdir_factory.mktemp('dcd').join('ncdf2dcd.dcd') + testfile = tmpdir_factory.mktemp("dcd").join("ncdf2dcd.dcd") testfile = str(testfile) ncdf = mda.Universe(PRMncdf, NCDF) with mda.Writer(testfile, n_atoms=ncdf.atoms.n_atoms) as w: @@ -392,32 +475,36 @@ def ncdf2dcd(tmpdir_factory): def test_ncdf2dcd_unitcell(ncdf2dcd): ncdf, dcd = ncdf2dcd for ts_ncdf, ts_dcd in zip(ncdf.trajectory, dcd.trajectory): - assert_almost_equal(ts_ncdf.dimensions, - ts_dcd.dimensions, - 3) + assert_almost_equal(ts_ncdf.dimensions, ts_dcd.dimensions, 3) def test_ncdf2dcd_coords(ncdf2dcd): ncdf, dcd = ncdf2dcd for ts_ncdf, ts_dcd in zip(ncdf.trajectory, dcd.trajectory): - assert_almost_equal(ts_ncdf.positions, - ts_dcd.positions, - 3) - -@pytest.fixture(params=[(PSF, DCD), - (PSF_TRICLINIC, DCD_TRICLINIC), - (PSF_NAMD_TRICLINIC, DCD_NAMD_TRICLINIC), - (PSF_NAMD_GBIS, DCD_NAMD_GBIS)]) + assert_almost_equal(ts_ncdf.positions, ts_dcd.positions, 3) + + +@pytest.fixture( + params=[ + (PSF, DCD), + (PSF_TRICLINIC, DCD_TRICLINIC), + (PSF_NAMD_TRICLINIC, DCD_NAMD_TRICLINIC), + (PSF_NAMD_GBIS, DCD_NAMD_GBIS), + ] +) def universe(request): psf, dcd = request.param yield mda.Universe(psf, dcd) + def test_ts_time(universe): # issue #1819 u = universe header = u.trajectory._file.header - ref_times = [(ts.frame + header['istart']/header['nsavc'])*ts.dt - for ts in u.trajectory] + ref_times = [ + (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 81b1aded06..63d0a09464 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_dlpoly.py +++ b/testsuite/MDAnalysisTests/coordinates/test_dlpoly.py @@ -24,12 +24,17 @@ import numpy as np import pytest -from numpy.testing import (assert_equal, assert_allclose) +from numpy.testing import assert_equal, assert_allclose -from MDAnalysisTests.datafiles import (DLP_CONFIG, DLP_CONFIG_minimal, - DLP_CONFIG_order, DLP_HISTORY, - DLP_HISTORY_minimal, DLP_HISTORY_order, - DLP_HISTORY_minimal_cell) +from MDAnalysisTests.datafiles import ( + DLP_CONFIG, + DLP_CONFIG_minimal, + DLP_CONFIG_order, + DLP_HISTORY, + DLP_HISTORY_minimal, + DLP_HISTORY_order, + DLP_HISTORY_minimal_cell, +) class _DLPConfig(object): @@ -46,10 +51,16 @@ def ts(self, rd): return rd.ts def test_read_unitcell(self, ts): - ref = np.array([[18.6960000000, 0.0000000000, 0.0000000000], - [0.0000000000, 18.6960000000, 0.0000000000], - [0.0000000000, 0.0000000000, 18.6960000000]]) - assert_allclose(ts.dimensions, mda.coordinates.core.triclinic_box(*ref)) + ref = np.array( + [ + [18.6960000000, 0.0000000000, 0.0000000000], + [0.0000000000, 18.6960000000, 0.0000000000], + [0.0000000000, 0.0000000000, 18.6960000000], + ] + ) + assert_allclose( + ts.dimensions, mda.coordinates.core.triclinic_box(*ref) + ) def test_positions(self, ts): ref = np.array([-7.608595309, -7.897790000, -7.892053559]) @@ -84,19 +95,19 @@ def test_read_unitcell(self): # cythonised class can no longer raise AttributeError # so changed to test of has_... properties def test_velocities(self, ts): - assert(ts.has_velocities == False) + assert ts.has_velocities == False def test_forces(self, ts): - assert(ts.has_forces == False) + assert ts.has_forces == False class _DLPConfig2(object): @pytest.fixture() def u(self): - return mda.Universe(self.f, format='CONFIG') + return mda.Universe(self.f, format="CONFIG") def test_names(self, u): - ref = ['C', 'B', 'A'] + ref = ["C", "B", "A"] assert_equal([a.name for a in u.atoms], ref) def test_pos(self, u): @@ -104,7 +115,7 @@ def test_pos(self, u): assert_allclose(u.atoms[2].position, ref) def test_vel(self, u): - ref = np.array([2.637614561, 0.5778767520E-01, -1.704765568]) + ref = np.array([2.637614561, 0.5778767520e-01, -1.704765568]) assert_allclose(u.atoms[2].velocity, ref) def test_for(self, u): @@ -135,8 +146,7 @@ def test_for(self): class _DLHistory(object): @pytest.fixture() def u(self): - return mda.Universe(self.f, format='HISTORY') - + return mda.Universe(self.f, format="HISTORY") def test_len(self, u): assert_equal(len(u.trajectory), 3) @@ -155,38 +165,64 @@ def test_slicing_2(self, u): assert_equal(nums, [1]) def test_position(self, u): - ref = np.array([[-7.595541651, -7.898808509, -7.861763110 - ], [-7.019565641, -7.264933320, -7.045213551], - [-6.787470785, -6.912685099, -6.922156843]]) + ref = np.array( + [ + [-7.595541651, -7.898808509, -7.861763110], + [-7.019565641, -7.264933320, -7.045213551], + [-6.787470785, -6.912685099, -6.922156843], + ] + ) for ts, r in zip(u.trajectory, ref): assert_allclose(u.atoms[0].position, r) def test_velocity(self, u): - ref = np.array([[1.109901682, -1.500264697, 4.752251711 - ], [-1.398479696, 2.091141311, 1.957430003], - [0.2570827995, -0.7146878577, -3.547444215]]) + ref = np.array( + [ + [1.109901682, -1.500264697, 4.752251711], + [-1.398479696, 2.091141311, 1.957430003], + [0.2570827995, -0.7146878577, -3.547444215], + ] + ) for ts, r in zip(u.trajectory, ref): assert_allclose(u.atoms[0].velocity, r) def test_force(self, u): - ref = np.array([[-2621.386432, 1579.334443, 1041.103241 - ], [-1472.262341, 2450.379615, -8149.916193], - [2471.802059, -3828.467296, 3596.679326]]) + ref = np.array( + [ + [-2621.386432, 1579.334443, 1041.103241], + [-1472.262341, 2450.379615, -8149.916193], + [2471.802059, -3828.467296, 3596.679326], + ] + ) for ts, r in zip(u.trajectory, ref): assert_allclose(u.atoms[0].force, r) def test_unitcell(self, u): - ref1 = np.array([[18.6796195135, 0.0000058913, -0.0000139999 - ], [0.0000058913, 18.6794658887, -0.0000016255], - [-0.0000139999, -0.0000016255, 18.6797229304]]) - ref2 = np.array([[17.2277221163, -0.0044216126, -0.0003229237 - ], [-0.0044205826, 17.2124253987, 0.0019439244], - [-0.0003226531, 0.0019445826, 17.2416976104]]) - ref3 = np.array([[16.5435673205, -0.0108424742, 0.0014935464 - ], [-0.0108333201, 16.5270298891, 0.0011094612], - [0.0014948739, 0.0011058349, 16.5725517831]]) + ref1 = np.array( + [ + [18.6796195135, 0.0000058913, -0.0000139999], + [0.0000058913, 18.6794658887, -0.0000016255], + [-0.0000139999, -0.0000016255, 18.6797229304], + ] + ) + ref2 = np.array( + [ + [17.2277221163, -0.0044216126, -0.0003229237], + [-0.0044205826, 17.2124253987, 0.0019439244], + [-0.0003226531, 0.0019445826, 17.2416976104], + ] + ) + ref3 = np.array( + [ + [16.5435673205, -0.0108424742, 0.0014935464], + [-0.0108333201, 16.5270298891, 0.0011094612], + [0.0014948739, 0.0011058349, 16.5725517831], + ] + ) 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): @@ -202,11 +238,11 @@ class TestDLPolyHistoryMinimal(_DLHistory): def test_velocity(self, u): with pytest.raises(mda.NoDataError): - getattr(u.atoms[0], 'velocity') + getattr(u.atoms[0], "velocity") def test_force(self, u): with pytest.raises(mda.NoDataError): - getattr(u.atoms[0], 'force') + getattr(u.atoms[0], "force") def test_unitcell(self): pass @@ -217,8 +253,8 @@ class TestDLPolyHistoryMinimalCell(_DLHistory): def test_velocity(self, u): with pytest.raises(mda.NoDataError): - getattr(u.atoms[0], 'velocity') + getattr(u.atoms[0], "velocity") def test_force(self, u): with pytest.raises(mda.NoDataError): - getattr(u.atoms[0], 'force') + getattr(u.atoms[0], "force") diff --git a/testsuite/MDAnalysisTests/coordinates/test_dms.py b/testsuite/MDAnalysisTests/coordinates/test_dms.py index 01823a6ec6..e4d9ac1ee6 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_dms.py +++ b/testsuite/MDAnalysisTests/coordinates/test_dms.py @@ -28,7 +28,7 @@ from MDAnalysis.lib.mdamath import triclinic_vectors -from MDAnalysisTests.datafiles import (DMS) +from MDAnalysisTests.datafiles import DMS class TestDMSReader(object): @@ -44,7 +44,7 @@ def test_global_cell(self, ts): assert ts.dimensions is None # cythonised class can no longer raise AttributeError - # so changed to test of has_velocities + # so changed to test of has_velocities def test_velocities(self, ts): assert_equal(ts.has_velocities, False) @@ -56,28 +56,39 @@ def test_number_of_coords(self, universe): def test_coords_atom_0(self, universe): # Desired coordinates taken directly from the SQLite file. Check unit # conversion - coords_0 = np.array([-11.0530004501343, - 26.6800003051758, - 12.7419996261597, ], - dtype=np.float32) + coords_0 = np.array( + [ + -11.0530004501343, + 26.6800003051758, + 12.7419996261597, + ], + dtype=np.float32, + ) 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") + assert_equal(universe.trajectory.time, 0.0, "wrong time of the frame") def test_frame(self, universe): - assert_equal(universe.trajectory.frame, 0, "wrong frame number " - "(0-based, should be 0 for single frame readers)") + assert_equal( + universe.trajectory.frame, + 0, + "wrong frame number " + "(0-based, should be 0 for single frame readers)", + ) def test_frame_index_0(self, universe): universe.trajectory[0] - assert_equal(universe.trajectory.ts.frame, 0, - "frame number for frame index 0 should be 0") + assert_equal( + universe.trajectory.ts.frame, + 0, + "frame number for frame index 0 should be 0", + ) def test_frame_index_1_raises_IndexError(self, universe): with pytest.raises(IndexError): diff --git a/testsuite/MDAnalysisTests/coordinates/test_fhiaims.py b/testsuite/MDAnalysisTests/coordinates/test_fhiaims.py index 463ddc5907..f1ec55b191 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_fhiaims.py +++ b/testsuite/MDAnalysisTests/coordinates/test_fhiaims.py @@ -27,54 +27,55 @@ import MDAnalysis as mda import numpy as np from MDAnalysisTests import make_Universe -from MDAnalysisTests.coordinates.base import ( - _SingleFrameReader, BaseWriterTest) +from MDAnalysisTests.coordinates.base import _SingleFrameReader, BaseWriterTest from MDAnalysisTests.datafiles import FHIAIMS -from numpy.testing import (assert_equal, - assert_array_almost_equal, - assert_almost_equal) +from numpy.testing import ( + assert_equal, + assert_array_almost_equal, + assert_almost_equal, +) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def universe(): return mda.Universe(FHIAIMS, FHIAIMS) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def universe_from_one_file(): return mda.Universe(FHIAIMS) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def ref(): return RefFHIAIMS() -@pytest.fixture(scope='class') +@pytest.fixture(scope="class") def good_input_natural_units(): - buffer = 'atom 0.1 0.2 0.3 H\natom 0.2 0.4 0.6 H\natom 0.3 0.6 0.9 H' + buffer = "atom 0.1 0.2 0.3 H\natom 0.2 0.4 0.6 H\natom 0.3 0.6 0.9 H" return StringIO(buffer) -@pytest.fixture(scope='class') +@pytest.fixture(scope="class") def good_input_with_velocity(): - buffer = 'atom 0.1 0.1 0.1 H\nvelocity 0.1 0.1 0.1' + buffer = "atom 0.1 0.1 0.1 H\nvelocity 0.1 0.1 0.1" return StringIO(buffer) class RefFHIAIMS(object): - from MDAnalysis.coordinates.FHIAIMS import (FHIAIMSReader, FHIAIMSWriter) + from MDAnalysis.coordinates.FHIAIMS import FHIAIMSReader, FHIAIMSWriter filename, trajectory, topology = [FHIAIMS] * 3 reader, writer = FHIAIMSReader, FHIAIMSWriter - pos_atom1 = np.asarray( - [6.861735, 2.103823, 37.753513], dtype=np.float32) + pos_atom1 = np.asarray([6.861735, 2.103823, 37.753513], dtype=np.float32) dimensions = np.asarray( - [18.6, 18.6, 55.8, 90., 90., 90.], dtype=np.float32) + [18.6, 18.6, 55.8, 90.0, 90.0, 90.0], dtype=np.float32 + ) n_atoms = 6 n_frames = 1 time = 0.0 - ext = '.in' + ext = ".in" prec = 6 container_format = True changing_dimensions = False @@ -84,88 +85,119 @@ class TestFHIAIMSReader(object): prec = 6 - @pytest.fixture(scope='class') + @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') + @pytest.fixture(scope="class") def bad_input_relative_positions_no_box(self): - buffer = 'atom_frac 0.1 0.1 0.1 H' + buffer = "atom_frac 0.1 0.1 0.1 H" return StringIO(buffer) - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def bad_input_missing_velocity(self): - buffer = 'atom 0.1 0.1 0.1 H\natom 0.2 0.2 0.2 H\nvelocity 0.1 0.1 0.1' + buffer = "atom 0.1 0.1 0.1 H\natom 0.2 0.2 0.2 H\nvelocity 0.1 0.1 0.1" return StringIO(buffer) - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def bad_input_velocity_wrong_position(self): - buffer = 'atom 0.1 0.1 0.1 H\natom 0.2 0.2 0.2 H\nvelocity 0.1 0.1 0.1\nvelocity 0.1 0.1 0.1' + buffer = "atom 0.1 0.1 0.1 H\natom 0.2 0.2 0.2 H\nvelocity 0.1 0.1 0.1\nvelocity 0.1 0.1 0.1" return StringIO(buffer) - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def bad_input_wrong_input_line(self): - buffer = 'garbage' + buffer = "garbage" return StringIO(buffer) - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def good_input_mixed_units(self): - buffer = 'lattice_vector 1.0 0.0 0.0\nlattice_vector 0.0 2.0 0.0\nlattice_vector 0.0 0.0 3.0\natom 0.1 0.2 0.3 H\natom_frac 0.2 0.2 0.2 H\natom_frac 0.3 0.3 0.3 H' + buffer = "lattice_vector 1.0 0.0 0.0\nlattice_vector 0.0 2.0 0.0\nlattice_vector 0.0 0.0 3.0\natom 0.1 0.2 0.3 H\natom_frac 0.2 0.2 0.2 H\natom_frac 0.3 0.3 0.3 H" return StringIO(buffer) def test_single_file(self, universe, universe_from_one_file): - assert_almost_equal(universe.atoms.positions, universe_from_one_file.atoms.positions, - self.prec, "FHIAIMSReader failed to load universe from single file") + assert_almost_equal( + universe.atoms.positions, + universe_from_one_file.atoms.positions, + self.prec, + "FHIAIMSReader failed to load universe from single file", + ) def test_uses_FHIAIMSReader(self, universe): from MDAnalysis.coordinates.FHIAIMS import FHIAIMSReader - assert isinstance(universe.trajectory, - FHIAIMSReader), "failed to choose FHIAIMSReader" + assert isinstance( + universe.trajectory, FHIAIMSReader + ), "failed to choose FHIAIMSReader" def test_dimensions(self, ref, universe): assert_almost_equal( - ref.dimensions, universe.dimensions, - self.prec, "FHIAIMSReader failed to get unitcell dimensions") + ref.dimensions, + universe.dimensions, + self.prec, + "FHIAIMSReader failed to get unitcell dimensions", + ) def test_n_atoms(self, ref, universe): assert_equal( - ref.n_atoms, universe.trajectory.n_atoms, - "FHIAIMSReader failed to get the right number of atoms") + ref.n_atoms, + universe.trajectory.n_atoms, + "FHIAIMSReader failed to get the right number of atoms", + ) def test_fhiaims_positions(self, ref, universe): # first particle - assert_almost_equal(ref.pos_atom1, - universe.atoms.positions[0], - self.prec, - "FHIAIMSReader failed to read coordinates properly") + assert_almost_equal( + ref.pos_atom1, + universe.atoms.positions[0], + self.prec, + "FHIAIMSReader failed to read coordinates properly", + ) def test_n_frames(self, ref, universe): - assert_equal(ref.n_frames, universe.trajectory.n_frames, - "wrong number of frames") + assert_equal( + ref.n_frames, + universe.trajectory.n_frames, + "wrong number of frames", + ) 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") - def test_bad_input_relative_positions_no_box(self, bad_input_relative_positions_no_box): - with pytest.raises(ValueError, match="Found relative coordinates in FHI-AIMS file without lattice info"): + def test_bad_input_relative_positions_no_box( + self, bad_input_relative_positions_no_box + ): + with pytest.raises( + ValueError, + match="Found relative coordinates in FHI-AIMS file without lattice info", + ): u = mda.Universe( - bad_input_relative_positions_no_box, format="FHIAIMS") + 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): - with pytest.raises(ValueError, match="Non-conforming line .velocity must follow"): + 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") + 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"): @@ -173,20 +205,26 @@ def test_bad_input_wrong_input_line(self, bad_input_wrong_input_line): def test_good_input_with_velocity(self, good_input_with_velocity): u = mda.Universe(good_input_with_velocity, format="FHIAIMS") - assert_almost_equal(u.atoms.velocities[0], - np.asarray([0.1, 0.1, 0.1]), - self.prec, - "FHIAIMSReader failed to read velocities properly") - - def test_mixed_units(self, good_input_natural_units, good_input_mixed_units): + assert_almost_equal( + u.atoms.velocities[0], + np.asarray([0.1, 0.1, 0.1]), + self.prec, + "FHIAIMSReader failed to read velocities properly", + ) + + 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) print(u_mixed.atoms.positions) - assert_almost_equal(u_natural.atoms.positions, - u_mixed.atoms.positions, - self.prec, - "FHIAIMSReader failed to read positions in lattice units properly") + assert_almost_equal( + u_natural.atoms.positions, + u_mixed.atoms.positions, + self.prec, + "FHIAIMSReader failed to read positions in lattice units properly", + ) class TestFHIAIMSWriter(BaseWriterTest): @@ -195,46 +233,60 @@ class TestFHIAIMSWriter(BaseWriterTest): @pytest.fixture def outfile(self, tmpdir): - return str(tmpdir.mkdir("FHIAIMSWriter").join('primitive-fhiaims-writer' + self.ext)) + return str( + tmpdir.mkdir("FHIAIMSWriter").join( + "primitive-fhiaims-writer" + self.ext + ) + ) def test_writer(self, universe, outfile): - """Test writing from a single frame FHIAIMS file to a FHIAIMS file. - """ + """Test writing from a single frame FHIAIMS file to a FHIAIMS file.""" universe.atoms.write(outfile) u = mda.Universe(FHIAIMS, outfile) - assert_almost_equal(u.atoms.positions, - universe.atoms.positions, self.prec, - err_msg="Writing FHIAIMS file with FHIAIMSWriter " - "does not reproduce original coordinates") + assert_almost_equal( + u.atoms.positions, + universe.atoms.positions, + self.prec, + err_msg="Writing FHIAIMS file with FHIAIMSWriter " + "does not reproduce original coordinates", + ) def test_writer_with_velocity(self, good_input_with_velocity, outfile): - """Test writing from a single frame FHIAIMS file to a FHIAIMS file. - """ + """Test writing from a single frame FHIAIMS file to a FHIAIMS file.""" universe_in = mda.Universe(good_input_with_velocity, format="FHIAIMS") universe_in.atoms.write(outfile) u = mda.Universe(outfile) - assert_almost_equal(u.atoms.velocities, - universe_in.atoms.velocities, self.prec, - err_msg="Writing FHIAIMS file with FHIAIMSWriter " - "does not reproduce original velocities") + assert_almost_equal( + u.atoms.velocities, + universe_in.atoms.velocities, + self.prec, + err_msg="Writing FHIAIMS file with FHIAIMSWriter " + "does not reproduce original velocities", + ) def test_writer_no_atom_names(self, u_no_names, outfile): u_no_names.atoms.write(outfile) u = mda.Universe(outfile) - expected = np.array(['X'] * u_no_names.atoms.n_atoms) + expected = np.array(["X"] * u_no_names.atoms.n_atoms) assert_equal(u.atoms.names, expected) def test_writer_with_n_atoms_none(self, good_input_natural_units, outfile): u = mda.Universe(good_input_natural_units, format="FHIAIMS") with mda.Writer(outfile, natoms=None) as w: w.write(u.atoms) - with open(outfile, 'r') as fhiaimsfile: + with open(outfile, "r") as fhiaimsfile: line = fhiaimsfile.readline().strip() assert line.startswith( - 'atom'), "Line written incorrectly with FHIAIMSWriter" + "atom" + ), "Line written incorrectly with FHIAIMSWriter" assert line.endswith( - 'H'), "Line written incorrectly with FHIAIMSWriter" + "H" + ), "Line written incorrectly with FHIAIMSWriter" line = np.asarray(line.split()[1:-1], dtype=np.float32) - assert_almost_equal(line, [0.1, 0.2, 0.3], self.prec, - err_msg="Writing FHIAIMS file with FHIAIMSWriter " - "does not reproduce original positions") + assert_almost_equal( + line, + [0.1, 0.2, 0.3], + self.prec, + err_msg="Writing FHIAIMS file with FHIAIMSWriter " + "does not reproduce original positions", + ) diff --git a/testsuite/MDAnalysisTests/coordinates/test_gms.py b/testsuite/MDAnalysisTests/coordinates/test_gms.py index 08ac1a9bcd..355e0658ba 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gms.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gms.py @@ -23,11 +23,11 @@ import pytest import numpy as np -from numpy.testing import (assert_equal, assert_almost_equal) +from numpy.testing import assert_equal, assert_almost_equal import MDAnalysis as mda from MDAnalysis.coordinates.GMS import GMSReader -from MDAnalysisTests.datafiles import (GMS_ASYMOPT, GMS_ASYMSURF, GMS_SYMOPT) +from MDAnalysisTests.datafiles import GMS_ASYMOPT, GMS_ASYMSURF, GMS_SYMOPT class _GMSBase(object): @@ -36,10 +36,11 @@ def u(self): return mda.Universe(self.filename) def test_n_frames(self, u): - assert_equal(u.trajectory.n_frames, - self.n_frames, - err_msg="Wrong number of frames read from {}".format( - self.flavour)) + assert_equal( + u.trajectory.n_frames, + self.n_frames, + err_msg="Wrong number of frames read from {}".format(self.flavour), + ) def test_random_access(self, u): u = u @@ -59,12 +60,12 @@ def test_random_access(self, u): @staticmethod def _calcFD(u): u.trajectory.rewind() - pp = (u.trajectory.ts._pos[0] - u.trajectory.ts._pos[3]) - z1 = np.sqrt(sum(pp ** 2)) + pp = u.trajectory.ts._pos[0] - u.trajectory.ts._pos[3] + z1 = np.sqrt(sum(pp**2)) for i in range(5): u.trajectory.next() - pp = (u.trajectory.ts._pos[0] - u.trajectory.ts._pos[3]) - z2 = np.sqrt(sum(pp ** 2)) + pp = u.trajectory.ts._pos[0] - u.trajectory.ts._pos[3] + z2 = np.sqrt(sum(pp**2)) return z1 - z2 def test_rewind(self, u): @@ -77,15 +78,18 @@ 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(self._calcFD(u), self.step5d, decimal=5, - err_msg="Wrong 1-4 atom distance change after " - "5 steps for {}".format(self.flavour)) + assert_almost_equal( + self._calcFD(u), + self.step5d, + decimal=5, + err_msg="Wrong 1-4 atom distance change after " + "5 steps for {}".format(self.flavour), + ) class TestGMSReader(_GMSBase): diff --git a/testsuite/MDAnalysisTests/coordinates/test_gro.py b/testsuite/MDAnalysisTests/coordinates/test_gro.py index 7dcdbbc029..c307bdc8ca 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gro.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gro.py @@ -28,7 +28,9 @@ from MDAnalysis.transformations import translate from MDAnalysisTests import make_Universe from MDAnalysisTests.coordinates.base import ( - BaseReference, BaseReaderTest, BaseWriterTest, + BaseReference, + BaseReaderTest, + BaseWriterTest, ) from MDAnalysisTests.coordinates.reference import RefAdK from MDAnalysisTests.datafiles import ( @@ -53,63 +55,79 @@ class TestGROReaderOld(RefAdK): # lower prec in gro!! (3 decimals nm -> 2 decimals in Angstroem) prec = 2 - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def universe(self): return mda.Universe(GRO) def test_load_gro(self, universe): U = universe - 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], "Atom selections") + 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], + "Atom selections", + ) def test_coordinates(self, universe): - A10CA = universe.select_atoms('name CA')[10] - assert_almost_equal(A10CA.position, - self.ref_coordinates['A10CA'], - self.prec, - err_msg="wrong coordinates for A10:CA") + A10CA = universe.select_atoms("name CA")[10] + assert_almost_equal( + A10CA.position, + self.ref_coordinates["A10CA"], + self.prec, + err_msg="wrong coordinates for A10:CA", + ) def test_distances(self, universe): # NOTe that the prec is only 1 decimal: subtracting two low precision # coordinates low prec: 9.3455122920041109; high prec (from pdb): # 9.3513174 - NTERM = universe.select_atoms('name N')[0] - CTERM = universe.select_atoms('name C')[-1] + NTERM = universe.select_atoms("name N")[0] + CTERM = universe.select_atoms("name C")[-1] d = mda.lib.mdamath.norm(NTERM.position - CTERM.position) - assert_almost_equal(d, self.ref_distances['endtoend'], self.prec - 1, - err_msg="distance between M1:N and G214:C") + assert_almost_equal( + d, + self.ref_distances["endtoend"], + self.prec - 1, + err_msg="distance between M1:N and G214:C", + ) def test_selection(self, universe): - na = universe.select_atoms('resname NA+') - assert_equal(len(na), self.ref_Na_sel_size, - "Atom selection of last atoms in file") + na = universe.select_atoms("resname NA+") + assert_equal( + len(na), + self.ref_Na_sel_size, + "Atom selection of last atoms in file", + ) def test_unitcell(self, universe): assert_almost_equal( universe.trajectory.ts.dimensions, self.ref_unitcell, self.prec, - err_msg="unit cell dimensions (rhombic dodecahedron)") + err_msg="unit cell dimensions (rhombic dodecahedron)", + ) class TestGROReaderNoConversionOld(RefAdK): prec = 3 - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def universe(self): return mda.Universe(GRO, convert_units=False) def test_coordinates(self, universe): # note: these are the native coordinates in nm; for the test to succeed # we loaded with convert_units=False - A10CA = universe.select_atoms('name CA')[10] + A10CA = universe.select_atoms("name CA")[10] # coordinates in nm - assert_almost_equal(A10CA.position, - RefAdK.ref_coordinates['A10CA'] / 10.0, - self.prec, err_msg="wrong native coordinates " - "(in nm) for A10:CA") + assert_almost_equal( + A10CA.position, + RefAdK.ref_coordinates["A10CA"] / 10.0, + self.prec, + err_msg="wrong native coordinates " "(in nm) for A10:CA", + ) def test_distances(self, universe): # 3 decimals on nm in gro but we compare to the distance @@ -118,13 +136,16 @@ def test_distances(self, universe): # Arrays are not almost equal distance between M1:N and G214:C # ACTUAL: 0.93455122920041123 # DESIRED: 0.93513173999999988 - NTERM = universe.select_atoms('name N')[0] - CTERM = universe.select_atoms('name C')[-1] + NTERM = universe.select_atoms("name N")[0] + CTERM = universe.select_atoms("name C")[-1] d = mda.lib.mdamath.norm(NTERM.position - CTERM.position) # coordinates in nm - assert_almost_equal(d, RefAdK.ref_distances['endtoend'] / 10.0, - self.prec - 1, err_msg="distance between M1:N " - "and G214:C") + assert_almost_equal( + d, + RefAdK.ref_distances["endtoend"] / 10.0, + self.prec - 1, + err_msg="distance between M1:N " "and G214:C", + ) def test_unitcell(self, universe): # lengths in A : convert to nm @@ -132,21 +153,24 @@ def test_unitcell(self, universe): universe.trajectory.ts.dimensions[:3], self.ref_unitcell[:3] / 10.0, self.prec, - err_msg="unit cell A,B,C (rhombic dodecahedron)") + err_msg="unit cell A,B,C (rhombic dodecahedron)", + ) # angles should not have changed assert_almost_equal( universe.trajectory.ts.dimensions[3:], self.ref_unitcell[3:], self.prec, - err_msg="unit cell alpha,beta,gamma (rhombic dodecahedron)") + err_msg="unit cell alpha,beta,gamma (rhombic dodecahedron)", + ) def test_volume(self, universe): # ref lengths in A (which was originally converted from nm) assert_almost_equal( universe.trajectory.ts.volume, - self.ref_volume / 1000., + self.ref_volume / 1000.0, 3, - err_msg="wrong volume for unitcell (rhombic dodecahedron)") + err_msg="wrong volume for unitcell (rhombic dodecahedron)", + ) class GROReference(BaseReference): @@ -156,30 +180,32 @@ def __init__(self): self.topology = COORDINATES_GRO self.reader = GROReader self.writer = GROWriter - self.ext = 'gro' + self.ext = "gro" self.n_frames = 1 self.prec = 4 self.first_frame.velocities = np.array( - [[0.0000, 0.100, 0.200], - [0.300, 0.400, 0.500], - [0.600, 0.700, 0.800], - [0.900, 1.000, 1.100], - [1.200, 1.300, 1.400]], - dtype=np.float32) + [ + [0.0000, 0.100, 0.200], + [0.300, 0.400, 0.500], + [0.600, 0.700, 0.800], + [0.900, 1.000, 1.100], + [1.200, 1.300, 1.400], + ], + dtype=np.float32, + ) self.totaltime = 0 self.container_format = True class TestGROReader(BaseReaderTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GROReference() def test_time(self, ref, reader): u = mda.Universe(ref.topology, ref.trajectory) - assert_equal(u.trajectory.time, 0.0, - "wrong time of the frame") + assert_equal(u.trajectory.time, 0.0, "wrong time of the frame") def test_full_slice(self, ref, reader): u = mda.Universe(ref.topology, ref.trajectory) @@ -190,30 +216,29 @@ def test_full_slice(self, ref, reader): class TestGROWriter(BaseWriterTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GROReference() def test_write_velocities(self, ref, tmpdir): u = mda.Universe(ref.topology, ref.trajectory) with tmpdir.as_cwd(): - outfile = 'write-velocities-test.' + ref.ext + outfile = "write-velocities-test." + ref.ext u.atoms.write(outfile) u2 = mda.Universe(outfile) - assert_almost_equal(u.atoms.velocities, - u2.atoms.velocities) + assert_almost_equal(u.atoms.velocities, u2.atoms.velocities) def test_write_no_resnames(self, u_no_resnames, ref, tmpdir): - outfile = 'write-no-resnames-test.' + ref.ext + outfile = "write-no-resnames-test." + ref.ext with tmpdir.as_cwd(): u_no_resnames.atoms.write(outfile) u = mda.Universe(outfile) - expected = np.array(['UNK'] * u_no_resnames.atoms.n_atoms) + expected = np.array(["UNK"] * u_no_resnames.atoms.n_atoms) assert_equal(u.atoms.resnames, expected) def test_write_no_resids(self, u_no_resids, ref, tmpdir): - outfile = 'write-no-resids-test.' + ref.ext + outfile = "write-no-resids-test." + ref.ext with tmpdir.as_cwd(): u_no_resids.atoms.write(outfile) u = mda.Universe(outfile) @@ -221,11 +246,11 @@ def test_write_no_resids(self, u_no_resids, ref, tmpdir): assert_equal(u.residues.resids, expected) def test_writer_no_atom_names(self, u_no_names, ref, tmpdir): - outfile = 'write-no-names-test.' + ref.ext + outfile = "write-no-names-test." + ref.ext with tmpdir.as_cwd(): u_no_names.atoms.write(outfile) u = mda.Universe(outfile) - expected = np.array(['X'] * u_no_names.atoms.n_atoms) + expected = np.array(["X"] * u_no_names.atoms.n_atoms) assert_equal(u.atoms.names, expected) def test_check_coordinate_limits_min(self, ref, tmpdir): @@ -235,7 +260,7 @@ def test_check_coordinate_limits_min(self, ref, tmpdir): # parallel tests u = mda.Universe(GRO) u.atoms[2000].position = [11.589, -999.9995 * 10, 22.2] # nm -> A - outfile = 'coordinate-limits-min-test.' + ref.ext + outfile = "coordinate-limits-min-test." + ref.ext with tmpdir.as_cwd(): with pytest.raises(ValueError): u.atoms.write(outfile) @@ -248,7 +273,7 @@ def test_check_coordinate_limits_max(self, ref, tmpdir): u = mda.Universe(GRO) # nm -> A ; [ob] 9999.9996 not caught u.atoms[1000].position = [0, 9999.9999 * 10, 1] - outfile = 'coordinate-limits-max-test.' + ref.ext + outfile = "coordinate-limits-max-test." + ref.ext with tmpdir.as_cwd(): with pytest.raises(ValueError): u.atoms.write(outfile) @@ -260,7 +285,7 @@ def test_check_coordinate_limits_max_noconversion(self, ref, tmpdir): # parallel tests u = mda.Universe(GRO, convert_units=False) u.atoms[1000].position = [22.2, 9999.9999, 37.89] - outfile = 'coordinate-limits-max-noconversion-test.' + ref.ext + outfile = "coordinate-limits-max-noconversion-test." + ref.ext with tmpdir.as_cwd(): with pytest.raises(ValueError): u.atoms.write(outfile, convert_units=False) @@ -277,38 +302,48 @@ def __init__(self): class TestGROReaderNoConversion(BaseReaderTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GRONoConversionReference() @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def reader(ref): reader = ref.reader(ref.trajectory, convert_units=False) - reader.add_auxiliary('lowf', ref.aux_lowf, - dt=ref.aux_lowf_dt, - initial_time=0, time_selector=None) - reader.add_auxiliary('highf', ref.aux_highf, - dt=ref.aux_highf_dt, - initial_time=0, time_selector=None) + reader.add_auxiliary( + "lowf", + ref.aux_lowf, + dt=ref.aux_lowf_dt, + initial_time=0, + time_selector=None, + ) + reader.add_auxiliary( + "highf", + ref.aux_highf, + dt=ref.aux_highf_dt, + initial_time=0, + time_selector=None, + ) return reader - + @staticmethod - @pytest.fixture(scope='class') + @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 class TestGROWriterNoConversion(BaseWriterTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GRONoConversionReference() @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def writer(ref): return ref.writer(ref.trajectory, convert_units=False) @@ -319,24 +354,27 @@ def __init__(self): self.trajectory = COORDINATES_GRO_INCOMPLETE_VELOCITY self.topology = COORDINATES_GRO_INCOMPLETE_VELOCITY self.first_frame.velocities = np.array( - [[0.0000, 0.100, 0.200], - [0.000, 0.000, 0.000], - [0.600, 0.700, 0.800], - [0.900, 1.000, 1.100], - [1.200, 1.300, 1.400]], - dtype=np.float32) + [ + [0.0000, 0.100, 0.200], + [0.000, 0.000, 0.000], + [0.600, 0.700, 0.800], + [0.900, 1.000, 1.100], + [1.200, 1.300, 1.400], + ], + dtype=np.float32, + ) class TestGROReaderIncompleteVelocities(BaseReaderTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GROReaderIncompleteVelocitiesReference() class TestGROWriterIncompleteVelocities(BaseWriterTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GROReaderIncompleteVelocitiesReference() @@ -350,14 +388,14 @@ def __init__(self): class TestGROBZ2Reader(BaseReaderTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GROBZReference() class TestGROBZ2Writer(BaseWriterTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GROBZReference() @@ -371,7 +409,7 @@ def __init__(self): class TestGROLargeWriter(BaseWriterTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return GROLargeReference() @@ -380,26 +418,30 @@ def test_writer_large(self, ref, tmpdir): Test that atom numbers are truncated for large GRO files (Issue 550). """ - outfile = 'outfile1.' + ref.ext + outfile = "outfile1." + ref.ext u = mda.Universe(ref.topology, ref.trajectory) with tmpdir.as_cwd(): u.atoms.write(outfile) - with open(outfile, 'rt') as mda_output: - with mda.lib.util.anyopen(ref.topology, 'rt') as expected_output: + with open(outfile, "rt") as mda_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(produced_lines, - expected_lines, - err_msg="Writing GRO file with > 100 000 " - "coords does not truncate properly.") + assert_equal( + produced_lines, + expected_lines, + err_msg="Writing GRO file with > 100 000 " + "coords does not truncate properly.", + ) def test_writer_large_residue_count(self, ref, tmpdir): """ Ensure large residue number truncation for GRO files (Issue 886). """ - outfile = 'outfile2.' + ref.ext + outfile = "outfile2." + ref.ext u = mda.Universe(ref.topology, ref.trajectory) target_resname = u.residues[-1].resname resid_value = 9999999 @@ -407,78 +449,81 @@ def test_writer_large_residue_count(self, ref, tmpdir): with tmpdir.as_cwd(): u.atoms.write(outfile) - with open(outfile, 'rt') as mda_output: + with open(outfile, "rt") as mda_output: output_lines = mda_output.readlines() produced_resid = output_lines[-2].split(target_resname)[0] expected_resid = str(resid_value)[:5] - assert_equal(produced_resid, - expected_resid, - err_msg="Writing GRO file with > 99 999 " - "resids does not truncate properly.") + assert_equal( + produced_resid, + expected_resid, + err_msg="Writing GRO file with > 99 999 " + "resids does not truncate properly.", + ) def test_growriter_resid_truncation(tmpdir): with tmpdir.as_cwd(): - u = make_Universe(extras=['resids'], trajectory=True) + u = make_Universe(extras=["resids"], trajectory=True) u.residues[0].resid = 123456789 - u.atoms.write('out.gro') + u.atoms.write("out.gro") - with open('out.gro', 'r') as grofile: + with open("out.gro", "r") as grofile: grofile.readline() grofile.readline() line = grofile.readline() # larger digits should get truncated - assert line.startswith('56789UNK') + assert line.startswith("56789UNK") + class TestGrowriterReindex(object): @pytest.fixture() def u(self): - gro = '''test + gro = """test 1 2CL CL20850 0.000 0.000 0.000 -7.29748 7.66094 9.82962''' - u = mda.Universe(StringIO(gro), format='gro') +7.29748 7.66094 9.82962""" + u = mda.Universe(StringIO(gro), format="gro") u.atoms[0].id = 3 return u def test_growriter_resid_true(self, u, tmpdir): with tmpdir.as_cwd(): - u.atoms.write('temp.gro', reindex=True) + u.atoms.write("temp.gro", reindex=True) - with open('temp.gro', 'r') as grofile: + with open("temp.gro", "r") as grofile: grofile.readline() grofile.readline() line = grofile.readline() - assert line.startswith(' 2CL CL 1') + assert line.startswith(" 2CL CL 1") def test_growriter_resid_false(self, u, tmpdir): with tmpdir.as_cwd(): - u.atoms.write('temp.gro', reindex=False) - with open('temp.gro', 'r') as grofile: + u.atoms.write("temp.gro", reindex=False) + with open("temp.gro", "r") as grofile: grofile.readline() grofile.readline() line = grofile.readline() - assert line.startswith(' 2CL CL 3') + assert line.startswith(" 2CL CL 3") def test_writer_resid_false(self, u, tmpdir): with tmpdir.as_cwd(): - with mda.Writer('temp.gro', reindex=False) as w: + with mda.Writer("temp.gro", reindex=False) as w: w.write(u.atoms) - with open('temp.gro', 'r') as grofile: + with open("temp.gro", "r") as grofile: grofile.readline() grofile.readline() line = grofile.readline() - assert line.startswith(' 2CL CL 3') + assert line.startswith(" 2CL CL 3") def test_writer_resid_true(self, u, tmpdir): with tmpdir.as_cwd(): - with mda.Writer('temp.gro', reindex=True) as w: + with mda.Writer("temp.gro", reindex=True) as w: w.write(u.atoms) - with open('temp.gro', 'r') as grofile: + with open("temp.gro", "r") as grofile: grofile.readline() grofile.readline() line = grofile.readline() - assert line.startswith(' 2CL CL 1') + assert line.startswith(" 2CL CL 1") def test_multiframe_gro(): @@ -486,14 +531,18 @@ 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(): u = mda.Universe(GRO_huge_box) - assert_equal(u.dimensions, np.array([4.e+05, 4.e+05, 4.e+05, 90, 90, 90], - dtype=np.float32)) + assert_equal( + u.dimensions, + np.array([4.0e05, 4.0e05, 4.0e05, 90, 90, 90], dtype=np.float32), + ) gro_no_dims = """\ @@ -503,14 +552,14 @@ def test_huge_box_gro(): """ -@pytest.mark.parametrize('dims', [1, 2, 4, 5, 6, 7, 8]) +@pytest.mark.parametrize("dims", [1, 2, 4, 5, 6, 7, 8]) def test_bad_box(dims): - cell = ' '.join([str(float(i)) for i in range(dims)]) + cell = " ".join([str(float(i)) for i in range(dims)]) grofile = gro_no_dims + cell errmsg = "GRO unitcell has neither 3 nor 9 entries." with pytest.raises(ValueError, match=errmsg): - u = mda.Universe(StringIO(grofile), format='gro') + u = mda.Universe(StringIO(grofile), format="gro") def test_gro_empty_box_write_read(tmpdir): @@ -523,9 +572,9 @@ def test_gro_empty_box_write_read(tmpdir): with tmpdir.as_cwd(): wmsg = " setting unit cell to zeroed box" with pytest.warns(UserWarning, match=wmsg): - u.atoms.write('test.gro') + u.atoms.write("test.gro") wmsg = "treating as missing unit cell" with pytest.warns(UserWarning, match=wmsg): - u2 = mda.Universe('test.gro') + u2 = mda.Universe("test.gro") assert u2.dimensions is None diff --git a/testsuite/MDAnalysisTests/coordinates/test_gsd.py b/testsuite/MDAnalysisTests/coordinates/test_gsd.py index e6b6a79ae4..102b8391df 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gsd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gsd.py @@ -30,34 +30,36 @@ from MDAnalysisTests.datafiles import GSD -@pytest.mark.skipif(HAS_GSD, reason='gsd is installed') +@pytest.mark.skipif(HAS_GSD, reason="gsd is installed") def test_no_gsd_u_raises(): - with pytest.raises(ImportError, match='please install gsd'): + with pytest.raises(ImportError, match="please install gsd"): _ = mda.Universe(GSD) -@pytest.mark.skipif(HAS_GSD, reason='gsd is installed') +@pytest.mark.skipif(HAS_GSD, reason="gsd is installed") def test_gsd_reader_raises(): - with pytest.raises(ImportError, match='please install gsd'): - _ = GSDReader('foo') + with pytest.raises(ImportError, match="please install gsd"): + _ = GSDReader("foo") -@pytest.mark.skipif(not HAS_GSD, reason='gsd is not installed') +@pytest.mark.skipif(not HAS_GSD, reason="gsd is not installed") class TestGSDReader: - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def GSD_U(self): return mda.Universe(GSD) def test_gsd_positions(self, GSD_U): # first frame first particle GSD_U.trajectory[0] - assert_almost_equal(GSD_U.atoms.positions[0], - [-5.4000001 , -10.19999981, -10.19999981]) + assert_almost_equal( + GSD_U.atoms.positions[0], [-5.4000001, -10.19999981, -10.19999981] + ) # second frame first particle GSD_U.trajectory[1] - assert_almost_equal(GSD_U.atoms.positions[0], - [-5.58348083, -9.98546982, -10.17657185]) - + assert_almost_equal( + GSD_U.atoms.positions[0], [-5.58348083, -9.98546982, -10.17657185] + ) + def test_gsd_n_frames(self, GSD_U): assert len(GSD_U.trajectory) == 2 @@ -65,9 +67,9 @@ def test_gsd_dimensions(self, GSD_U): ts = GSD_U.trajectory[0] assert_almost_equal( ts.dimensions, - [21.60000038, 21.60000038, 21.60000038, 90., 90., 90.] + [21.60000038, 21.60000038, 21.60000038, 90.0, 90.0, 90.0], ) def test_gsd_data_step(self, GSD_U): - assert GSD_U.trajectory[0].data['step'] == 0 - assert GSD_U.trajectory[1].data['step'] == 500 + assert GSD_U.trajectory[0].data["step"] == 0 + assert GSD_U.trajectory[1].data["step"] == 500 diff --git a/testsuite/MDAnalysisTests/coordinates/test_h5md.py b/testsuite/MDAnalysisTests/coordinates/test_h5md.py index 76e80a2a46..1524ca7f62 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_h5md.py +++ b/testsuite/MDAnalysisTests/coordinates/test_h5md.py @@ -37,7 +37,7 @@ def __init__(self): self.topology = COORDINATES_TOPOLOGY self.reader = mda.coordinates.H5MD.H5MDReader self.writer = mda.coordinates.H5MD.H5MDWriter - self.ext = 'h5md' + self.ext = "h5md" self.prec = 3 self.changing_dimensions = True @@ -66,6 +66,7 @@ def iter_ts(self, i): @pytest.mark.skipif(not HAS_H5PY, reason="h5py not installed") class TestH5MDReaderBaseAPI(MultiframeReaderTest): """Tests H5MDReader with with synthetic trajectory.""" + @staticmethod @pytest.fixture() def ref(): @@ -73,14 +74,14 @@ def ref(): def test_get_writer_1(self, ref, reader, tmpdir): with tmpdir.as_cwd(): - outfile = 'test-writer.' + ref.ext + outfile = "test-writer." + ref.ext with reader.Writer(outfile) as W: assert_equal(isinstance(W, ref.writer), True) assert_equal(W.n_atoms, reader.n_atoms) def test_get_writer_2(self, ref, reader, tmpdir): with tmpdir.as_cwd(): - outfile = 'test-writer.' + ref.ext + outfile = "test-writer." + ref.ext with reader.Writer(outfile, n_atoms=100) as W: assert_equal(isinstance(W, ref.writer), True) assert_equal(W.n_atoms, 100) @@ -88,25 +89,29 @@ def test_get_writer_2(self, ref, reader, tmpdir): def test_copying(self, ref, reader): # Issue #3664 - test not done in test_copying due to dependencies original = mda.coordinates.H5MD.H5MDReader( - ref.trajectory, convert_units=False, dt=2, - time_offset=10, foo="bar") + ref.trajectory, + convert_units=False, + dt=2, + time_offset=10, + foo="bar", + ) copy = original.copy() - assert original.format not in ('MEMORY', 'CHAIN') + assert original.format not in ("MEMORY", "CHAIN") assert original.convert_units is False assert copy.convert_units is False - assert original._ts_kwargs['time_offset'] == 10 - assert copy._ts_kwargs['time_offset'] == 10 - assert original._ts_kwargs['dt'] == 2 - assert copy._ts_kwargs['dt'] == 2 + assert original._ts_kwargs["time_offset"] == 10 + assert copy._ts_kwargs["time_offset"] == 10 + assert original._ts_kwargs["dt"] == 2 + assert copy._ts_kwargs["dt"] == 2 - assert original.ts.data['time_offset'] == 10 - assert copy.ts.data['time_offset'] == 10 + assert original.ts.data["time_offset"] == 10 + assert copy.ts.data["time_offset"] == 10 - assert original.ts.data['dt'] == 2 - assert copy.ts.data['dt'] == 2 + assert original.ts.data["dt"] == 2 + assert copy.ts.data["dt"] == 2 - assert copy._kwargs['foo'] == 'bar' + assert copy._kwargs["foo"] == "bar" # check coordinates assert original.ts.frame == copy.ts.frame @@ -122,27 +127,32 @@ def test_copying(self, ref, reader): @pytest.mark.skipif(not HAS_H5PY, reason="h5py not installed") class TestH5MDWriterBaseAPI(BaseWriterTest): """Tests H5MDWriter base API with synthetic trajectory""" + @staticmethod @pytest.fixture() def ref(): return H5MDReference() def test_write_trajectory_atomgroup(self, ref, reader, universe, tmpdir): - outfile = 'write-atoms-test.' + ref.ext + outfile = "write-atoms-test." + ref.ext with tmpdir.as_cwd(): - with ref.writer(outfile, universe.atoms.n_atoms, - velocities=True, forces=True) as w: + with ref.writer( + outfile, universe.atoms.n_atoms, velocities=True, forces=True + ) as w: for ts in universe.trajectory: w.write(universe.atoms) self._check_copy(outfile, ref, reader) - @pytest.mark.xfail((os.name == 'nt' and sys.maxsize <= 2**32), - reason="occasional fail on 32-bit windows") + @pytest.mark.xfail( + (os.name == "nt" and sys.maxsize <= 2**32), + reason="occasional fail on 32-bit windows", + ) def test_write_trajectory_universe(self, ref, reader, universe, tmpdir): - outfile = 'write-uni-test.' + ref.ext + outfile = "write-uni-test." + ref.ext with tmpdir.as_cwd(): - with ref.writer(outfile, universe.atoms.n_atoms, - velocities=True, forces=True) as w: + with ref.writer( + outfile, universe.atoms.n_atoms, velocities=True, forces=True + ) as w: for ts in universe.trajectory: w.write(universe) self._check_copy(outfile, ref, reader) @@ -152,101 +162,137 @@ def test_write_trajectory_universe(self, ref, reader, universe, tmpdir): class TestH5MDReaderWithRealTrajectory(object): prec = 3 - ext = 'h5md' + ext = "h5md" - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def universe(self): return mda.Universe(TPR_xvf, H5MD_xvf) @pytest.fixture() def h5md_file(self): - return h5py.File(H5MD_xvf, 'r') + return h5py.File(H5MD_xvf, "r") @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir.join('h5md-reader-test.' + self.ext)) + return str(tmpdir.join("h5md-reader-test." + self.ext)) def test_n_frames(self, universe): assert len(universe.trajectory) == 3 def test_positions(self, universe): universe.trajectory[0] - assert_almost_equal(universe.atoms.positions[0], - [32.309906, 13.77798, 14.372463], - decimal=self.prec) - assert_almost_equal(universe.atoms.positions[42], - [28.116928, 19.405945, 19.647358], - decimal=self.prec) - assert_almost_equal(universe.atoms.positions[10000], - [44.117805, 50.442093, 23.299038], - decimal=self.prec) + assert_almost_equal( + universe.atoms.positions[0], + [32.309906, 13.77798, 14.372463], + decimal=self.prec, + ) + assert_almost_equal( + universe.atoms.positions[42], + [28.116928, 19.405945, 19.647358], + decimal=self.prec, + ) + assert_almost_equal( + universe.atoms.positions[10000], + [44.117805, 50.442093, 23.299038], + decimal=self.prec, + ) universe.trajectory[1] - assert_almost_equal(universe.atoms.positions[0], - [30.891968, 13.678971, 13.6000595], - decimal=self.prec) - assert_almost_equal(universe.atoms.positions[42], - [27.163246, 19.846561, 19.3582], - decimal=self.prec) - assert_almost_equal(universe.atoms.positions[10000], - [45.869278, 5.0342298, 25.460655], - decimal=self.prec) + assert_almost_equal( + universe.atoms.positions[0], + [30.891968, 13.678971, 13.6000595], + decimal=self.prec, + ) + assert_almost_equal( + universe.atoms.positions[42], + [27.163246, 19.846561, 19.3582], + decimal=self.prec, + ) + assert_almost_equal( + universe.atoms.positions[10000], + [45.869278, 5.0342298, 25.460655], + decimal=self.prec, + ) universe.trajectory[2] - assert_almost_equal(universe.atoms.positions[0], - [31.276512, 13.89617, 15.015897], - decimal=self.prec) - assert_almost_equal(universe.atoms.positions[42], - [28.567991, 20.56532, 19.40814], - decimal=self.prec) - assert_almost_equal(universe.atoms.positions[10000], - [39.713223, 6.127234, 18.284992], - decimal=self.prec) + assert_almost_equal( + universe.atoms.positions[0], + [31.276512, 13.89617, 15.015897], + decimal=self.prec, + ) + assert_almost_equal( + universe.atoms.positions[42], + [28.567991, 20.56532, 19.40814], + decimal=self.prec, + ) + assert_almost_equal( + universe.atoms.positions[10000], + [39.713223, 6.127234, 18.284992], + decimal=self.prec, + ) def test_h5md_velocities(self, universe): universe.trajectory[0] - assert_almost_equal(universe.atoms.velocities[0], - [-2.697732, 0.613568, 0.14334752], - decimal=self.prec) + assert_almost_equal( + universe.atoms.velocities[0], + [-2.697732, 0.613568, 0.14334752], + decimal=self.prec, + ) universe.trajectory[1] - assert_almost_equal(universe.atoms.velocities[42], - [-6.8698354, 7.834235, -8.114698], - decimal=self.prec) + assert_almost_equal( + universe.atoms.velocities[42], + [-6.8698354, 7.834235, -8.114698], + decimal=self.prec, + ) universe.trajectory[2] - assert_almost_equal(universe.atoms.velocities[10000], - [9.799492, 5.631466, 6.852126], - decimal=self.prec) + assert_almost_equal( + universe.atoms.velocities[10000], + [9.799492, 5.631466, 6.852126], + decimal=self.prec, + ) def test_h5md_forces(self, universe): universe.trajectory[0] - assert_almost_equal(universe.atoms.forces[0], - [20.071287, -155.2285, -96.72112], - decimal=self.prec) + assert_almost_equal( + universe.atoms.forces[0], + [20.071287, -155.2285, -96.72112], + decimal=self.prec, + ) universe.trajectory[1] - assert_almost_equal(universe.atoms.forces[42], - [-4.1959066, -31.31548, 22.663044], - decimal=self.prec) + assert_almost_equal( + universe.atoms.forces[42], + [-4.1959066, -31.31548, 22.663044], + decimal=self.prec, + ) universe.trajectory[2] - assert_almost_equal(universe.atoms.forces[10000], - [-41.43743, 83.35207, 62.94751], - decimal=self.prec) + assert_almost_equal( + universe.atoms.forces[10000], + [-41.43743, 83.35207, 62.94751], + decimal=self.prec, + ) def test_h5md_dimensions(self, universe): universe.trajectory[0] - assert_almost_equal(universe.trajectory.ts.dimensions, - [52.763, 52.763, 52.763, 90., 90., 90.], - decimal=self.prec) + assert_almost_equal( + universe.trajectory.ts.dimensions, + [52.763, 52.763, 52.763, 90.0, 90.0, 90.0], + decimal=self.prec, + ) universe.trajectory[1] - assert_almost_equal(universe.trajectory.ts.dimensions, - [52.807877, 52.807877, 52.807877, 90., 90., 90.], - decimal=self.prec) + assert_almost_equal( + universe.trajectory.ts.dimensions, + [52.807877, 52.807877, 52.807877, 90.0, 90.0, 90.0], + decimal=self.prec, + ) universe.trajectory[2] - assert_almost_equal(universe.trajectory.ts.dimensions, - [52.839806, 52.839806, 52.839806, 90., 90., 90.], - decimal=self.prec) + assert_almost_equal( + universe.trajectory.ts.dimensions, + [52.839806, 52.839806, 52.839806, 90.0, 90.0, 90.0], + decimal=self.prec, + ) def test_h5md_data_step(self, universe): for ts, step in zip(universe.trajectory, (0, 25000, 50000)): - assert_equal(ts.data['step'], step) + assert_equal(ts.data["step"], step) def test_rewind(self, universe): universe.trajectory[1] @@ -262,155 +308,176 @@ def test_jump_last_frame(self, universe): universe.trajectory[-1] assert universe.trajectory.ts.frame == 2 - @pytest.mark.parametrize("start, stop, step", ((0, 2, 1), - (1, 2, 1))) + @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]] + frames = [ + 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('group, attr', (('position', 'positions'), - ('velocity', 'velocities'), - ('force', 'forces'))) + @pytest.mark.parametrize( + "group, attr", + ( + ("position", "positions"), + ("velocity", "velocities"), + ("force", "forces"), + ), + ) def test_no_group(self, h5md_file, outfile, attr, group): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - del g[f'particles/trajectory/{group}'] + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + del g[f"particles/trajectory/{group}"] u = mda.Universe(TPR_xvf, outfile) - with pytest.raises(NoDataError, - match="This Timestep has no"): + with pytest.raises(NoDataError, match="This Timestep has no"): getattr(u.trajectory.ts, attr) - @pytest.mark.parametrize('dset', - ('position/value', 'position/time', 'velocity/value', 'force/value')) + @pytest.mark.parametrize( + "dset", + ("position/value", "position/time", "velocity/value", "force/value"), + ) def test_unknown_unit(self, h5md_file, outfile, dset): with h5md_file as f: - 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."): + 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." + ): u = mda.Universe(TPR_xvf, outfile) def test_length_unit_from_box(self, h5md_file, universe, outfile): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - del g['particles/trajectory/position'] + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + 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')) + @pytest.mark.parametrize("group", ("position", "velocity", "force")) def test_changing_n_atoms(self, h5md_file, outfile, group): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - g[f'particles/trajectory/{group}/value'].resize((3, 10000, 3)) - with pytest.raises(ValueError, - match=" of either the postion, velocity, or force"): + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + g[f"particles/trajectory/{group}/value"].resize((3, 10000, 3)) + with pytest.raises( + ValueError, match=" of either the postion, velocity, or force" + ): u = mda.Universe(TPR_xvf, outfile) def test_2D_box(self, h5md_file, outfile): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) new_box = np.ones(shape=(3, 2, 2)) - g['particles/trajectory/box'].attrs['dimension'] = 2 - del g['particles/trajectory/box/edges/value'] - g['particles/trajectory' - '/box/edges'].create_dataset('value', data=new_box) - with pytest.raises(ValueError, - match="MDAnalysis only supports 3-dimensional"): + g["particles/trajectory/box"].attrs["dimension"] = 2 + del g["particles/trajectory/box/edges/value"] + g["particles/trajectory" "/box/edges"].create_dataset( + "value", data=new_box + ) + with pytest.raises( + ValueError, match="MDAnalysis only supports 3-dimensional" + ): u = mda.Universe(TPR_xvf, outfile) def test_box_vector(self, h5md_file, outfile): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) vector = [1, 2, 3] - del g['particles/trajectory/box/edges'] - g['particles/trajectory/box/edges/value'] = [vector, vector, vector] + del g["particles/trajectory/box/edges"] + g["particles/trajectory/box/edges/value"] = [ + vector, + vector, + vector, + ] u = mda.Universe(TPR_xvf, outfile) # values in vector are conveted from nm -> Angstrom assert_equal(u.trajectory.ts.dimensions, [10, 20, 30, 90, 90, 90]) def test_no_box(self, h5md_file, outfile): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - del g['particles/trajectory/box/edges'] + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + del g["particles/trajectory/box/edges"] u = mda.Universe(TPR_xvf, outfile) assert_equal(u.trajectory.ts.dimensions, None) def test_no_groups(self, h5md_file, outfile): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - 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 h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + 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" + ): u = mda.Universe(TPR_xvf, outfile) def test_no_convert_units(self, h5md_file, outfile): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - groups = ['position', 'velocity', 'force'] + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + groups = ["position", "velocity", "force"] for name in groups: - del g['particles/trajectory'][name]['value'].attrs['unit'] - del g['particles/trajectory/position/time'].attrs['unit'] + del g["particles/trajectory"][name]["value"].attrs["unit"] + del g["particles/trajectory/position/time"].attrs["unit"] u = mda.Universe(TPR_xvf, outfile, convert_units=False) for unit in u.trajectory.units: assert_equal(u.trajectory.units[unit], None) def test_no_units_but_convert_units_true_error(self, h5md_file, outfile): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - groups = ['position', 'velocity', 'force'] + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + groups = ["position", "velocity", "force"] for name in groups: - 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"): + 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" + ): u = mda.Universe(TPR_xvf, outfile, convert_units=True) - @pytest.mark.xfail(reason='Issue #2884') + @pytest.mark.xfail(reason="Issue #2884") def test_open_filestream(self, h5md_file, universe): with h5md_file as f: u = mda.Universe(TPR_xvf, h5md_file) @@ -420,29 +487,41 @@ def test_open_filestream(self, h5md_file, universe): assert_equal(ts1.forces, ts2.forces) def test_wrong_driver(self): - with pytest.raises(ValueError, - match="If MPI communicator object is used to open"): - u = mda.Universe(TPR_xvf, H5MD_xvf, - driver='wrong_driver', - comm="mock MPI.COMM_WORLD") + with pytest.raises( + ValueError, match="If MPI communicator object is used to open" + ): + u = mda.Universe( + TPR_xvf, + H5MD_xvf, + driver="wrong_driver", + comm="mock MPI.COMM_WORLD", + ) def test_open_with_driver(self): u = mda.Universe(TPR_xvf, H5MD_xvf, driver="core") assert_equal(u.trajectory._file.driver, "core") - @pytest.mark.parametrize('group1, group2', (('velocity', 'force'), - ('position', 'force'), - ('position', 'velocity'))) + @pytest.mark.parametrize( + "group1, group2", + ( + ("velocity", "force"), + ("position", "force"), + ("position", "velocity"), + ), + ) def test_parse_n_atoms(self, h5md_file, outfile, group1, group2): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - traj_group = g['particles/trajectory'] + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + traj_group = g["particles/trajectory"] del traj_group[group1] del traj_group[group2] - for dset in ('position/value', 'velocity/value', - 'force/value'): + for dset in ( + "position/value", + "velocity/value", + "force/value", + ): try: n_atoms_in_dset = traj_group[dset].shape[1] break @@ -454,13 +533,13 @@ def test_parse_n_atoms(self, h5md_file, outfile, group1, group2): def test_parse_n_atoms_error(self, h5md_file, outfile): with h5md_file as f: - with h5py.File(outfile, 'w') as g: - f.copy(source='particles', dest=g) - f.copy(source='h5md', dest=g) - traj_group = g['particles/trajectory'] - del traj_group['position'] - del traj_group['velocity'] - del traj_group['force'] + with h5py.File(outfile, "w") as g: + f.copy(source="particles", dest=g) + f.copy(source="h5md", dest=g) + traj_group = g["particles/trajectory"] + del traj_group["position"] + del traj_group["velocity"] + del traj_group["force"] errmsg = "Could not construct minimal topology" with pytest.raises(ValueError, match=errmsg): @@ -479,10 +558,10 @@ def universe(self): @pytest.fixture() def universe_no_units(self): u = mda.Universe(TPR_xvf, H5MD_xvf, convert_units=False) - u.trajectory.units['time'] = None - u.trajectory.units['length'] = None - u.trajectory.units['velocity'] = None - u.trajectory.units['force'] = None + u.trajectory.units["time"] = None + u.trajectory.units["length"] = None + u.trajectory.units["velocity"] = None + u.trajectory.units["force"] = None return u @pytest.fixture() @@ -491,17 +570,22 @@ def Writer(self): @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir) + 'h5md-writer-test.h5md' + return str(tmpdir) + "h5md-writer-test.h5md" @pytest.fixture() def outtop(self, tmpdir): - return str(tmpdir) + 'h5md-writer-top.pdb' - - @pytest.mark.parametrize('scalar, error, match', - ((0, ValueError, "H5MDWriter: no atoms in output trajectory"), - (0.5, IOError, "H5MDWriter: Timestep does not have"))) - def test_n_atoms_errors(self, universe, Writer, outfile, - scalar, error, match): + return str(tmpdir) + "h5md-writer-top.pdb" + + @pytest.mark.parametrize( + "scalar, error, match", + ( + (0, ValueError, "H5MDWriter: no atoms in output trajectory"), + (0.5, IOError, "H5MDWriter: Timestep does not have"), + ), + ) + 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: @@ -515,7 +599,7 @@ def test_chunk_error(self, universe, Writer, outfile): for ts in universe.trajectory: W.write(universe) - @pytest.mark.parametrize('dimensions', (None, 0)) + @pytest.mark.parametrize("dimensions", (None, 0)) def test_no_dimensions(self, universe, Writer, outfile, dimensions): with Writer(outfile, universe.atoms.n_atoms) as W: for ts in universe.trajectory: @@ -523,34 +607,36 @@ def test_no_dimensions(self, universe, Writer, outfile, dimensions): W.write(universe) uw = mda.Universe(TPR_xvf, outfile) - box = uw.trajectory._particle_group['box'] - assert 'edges' not in box - assert_equal(3*['none'], box.attrs['boundary']) - assert_equal(3, box.attrs['dimension']) + box = uw.trajectory._particle_group["box"] + assert "edges" not in box + assert_equal(3 * ["none"], box.attrs["boundary"]) + assert_equal(3, box.attrs["dimension"]) def test_step_not_monotonic(self, universe, Writer, outfile): - with pytest.raises(ValueError, - match="The H5MD standard dictates that the step "): + with pytest.raises( + ValueError, match="The H5MD standard dictates that the step " + ): with Writer(outfile, universe.atoms.n_atoms) as W: for ts in universe.trajectory[[0, 1, 2, 1]]: W.write(universe) - with pytest.raises(ValueError, - match="The H5MD standard dictates that the step "): + with pytest.raises( + ValueError, match="The H5MD standard dictates that the step " + ): with Writer(outfile, universe.atoms.n_atoms) as W: for ts in universe.trajectory: if ts.frame == 2: - ts.data['step'] = 0 + ts.data["step"] = 0 W.write(universe) def test_step_from_frame(self, universe, Writer, outfile): with Writer(outfile, universe.atoms.n_atoms) as W: for ts in universe.trajectory: - del ts.data['step'] + del ts.data["step"] W.write(universe) uw = mda.Universe(TPR_xvf, outfile) - steps = [ts.data['step'] for ts in uw.trajectory] + steps = [ts.data["step"] for ts in uw.trajectory] frames = [ts.frame for ts in universe.trajectory] for step, frame in zip(steps, frames): assert_equal(step, frame) @@ -559,32 +645,39 @@ def test_has_property(self, universe, Writer, outfile): with Writer(outfile, universe.atoms.n_atoms) as W: W.write(universe) # make sure property is pulled from _has dict - assert W.has_positions == W._has['position'] - assert W.has_velocities == W._has['velocity'] - assert W.has_forces == W._has['force'] + assert W.has_positions == W._has["position"] + assert W.has_velocities == W._has["velocity"] + assert W.has_forces == W._has["force"] # make sure the values are correct assert W.has_positions is True assert W.has_velocities is True assert W.has_forces is True - @pytest.mark.parametrize('pos, vel, force', ( + @pytest.mark.parametrize( + "pos, vel, force", + ( (True, False, False), (True, True, False), (True, False, True), (True, True, True), (False, True, True), (False, False, True), - (False, False, False))) - def test_write_trajectory(self, universe, Writer, outfile, - pos, vel, force): + (False, False, False), + ), + ) + def test_write_trajectory( + self, universe, Writer, outfile, pos, vel, force + ): try: - with Writer(outfile, - universe.atoms.n_atoms, - positions=pos, - velocities=vel, - forces=force, - author='My Name', - author_email='my_email@asu.edu') as W: + with Writer( + outfile, + universe.atoms.n_atoms, + positions=pos, + velocities=vel, + forces=force, + author="My Name", + author_email="my_email@asu.edu", + ) as W: for ts in universe.trajectory: W.write(universe) @@ -592,38 +685,47 @@ def test_write_trajectory(self, universe, Writer, outfile, # 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"): - getattr(ts, 'positions') + 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"): - getattr(ts, 'velocities') + 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"): - getattr(ts, 'forces') + with pytest.raises( + NoDataError, match="This Timestep has no" + ): + getattr(ts, "forces") # when (False, False, False) - except(ValueError): - with pytest.raises(ValueError, - match="At least one of positions, velocities"): - with Writer(outfile, - universe.atoms.n_atoms, - positions=pos, - velocities=vel, - forces=force, - author='My Name', - author_email='my_email@asu.edu') as W: + except ValueError: + with pytest.raises( + ValueError, match="At least one of positions, velocities" + ): + with Writer( + outfile, + universe.atoms.n_atoms, + positions=pos, + velocities=vel, + forces=force, + author="My Name", + author_email="my_email@asu.edu", + ) as W: for ts in universe.trajectory: W.write(universe) @@ -638,90 +740,125 @@ def test_write_AtomGroup_with(self, universe, outfile, outtop, Writer): uw = mda.Universe(outtop, outfile) caw = uw.atoms - for orig_ts, written_ts in zip(universe.trajectory, - uw.trajectory): + 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) - - @pytest.mark.parametrize('frames, n_frames', ((None, 1), - ('all', 3))) - def test_ag_write(self, universe, outfile, outtop, - Writer, frames, n_frames): + 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 + ): """test to write with ag.write()""" ca = universe.select_atoms("protein and name CA") ca.write(outtop) - ca.write(outfile, frames=frames, format='h5md') + ca.write(outfile, frames=frames, format="h5md") uw = mda.Universe(outtop, outfile) caw = uw.atoms assert_equal(n_frames, len(uw.trajectory)) - for orig_ts, written_ts in zip(universe.trajectory, - uw.trajectory): + 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) - - @pytest.mark.parametrize('timeunit, lengthunit, velocityunit, forceunit', ( - ('fs', 'Angstrom', 'Angstrom/ps', 'kJ/(mol*Angstrom)'), - ('s', 'pm', 'm/s', 'Newton'), - ('ps', 'fm', 'Angstrom/fs', 'kcal/(mol*Angstrom)',), - ('AKMA', 'nm', 'Angstrom/AKMA', 'kcal/(mol*Angstrom)'))) - def test_write_custom_units(self, universe, outfile, Writer, - timeunit, lengthunit, - velocityunit, forceunit): - with Writer(outfile, - universe.atoms.n_atoms, - lengthunit=lengthunit, - velocityunit=velocityunit, - forceunit=forceunit, - timeunit=timeunit) as W: + assert_almost_equal( + written_ts.dimensions, orig_ts.dimensions, self.prec + ) + + @pytest.mark.parametrize( + "timeunit, lengthunit, velocityunit, forceunit", + ( + ("fs", "Angstrom", "Angstrom/ps", "kJ/(mol*Angstrom)"), + ("s", "pm", "m/s", "Newton"), + ( + "ps", + "fm", + "Angstrom/fs", + "kcal/(mol*Angstrom)", + ), + ("AKMA", "nm", "Angstrom/AKMA", "kcal/(mol*Angstrom)"), + ), + ) + def test_write_custom_units( + self, + universe, + outfile, + Writer, + timeunit, + lengthunit, + velocityunit, + forceunit, + ): + with Writer( + outfile, + universe.atoms.n_atoms, + lengthunit=lengthunit, + velocityunit=velocityunit, + forceunit=forceunit, + timeunit=timeunit, + ) as W: for ts in universe.trajectory: W.write(universe) u = mda.Universe(TPR_xvf, outfile) - for u_unit, custom_unit in zip(u.trajectory.units.values(), - (timeunit, lengthunit, - velocityunit, forceunit)): + for u_unit, custom_unit in zip( + u.trajectory.units.values(), + (timeunit, lengthunit, velocityunit, forceunit), + ): assert_equal(u_unit, custom_unit) - @pytest.mark.parametrize('timeunit, lengthunit, velocityunit, forceunit', ( - ('imaginary time', None, None, None), - (None, None, 'c', None), - (None, None, None, 'HUGE FORCE',), - (None, 'lightyear', None, None),)) - def test_write_bad_units(self, universe, outfile, Writer, - timeunit, lengthunit, - velocityunit, forceunit): + @pytest.mark.parametrize( + "timeunit, lengthunit, velocityunit, forceunit", + ( + ("imaginary time", None, None, None), + (None, None, "c", None), + ( + None, + None, + None, + "HUGE FORCE", + ), + (None, "lightyear", None, None), + ), + ) + def test_write_bad_units( + self, + universe, + outfile, + Writer, + timeunit, + lengthunit, + velocityunit, + forceunit, + ): with pytest.raises(ValueError, match=" is not a unit recognized by"): - with Writer(outfile, - universe.atoms.n_atoms, - lengthunit=lengthunit, - velocityunit=velocityunit, - forceunit=forceunit, - timeunit=timeunit) as W: + with Writer( + outfile, + universe.atoms.n_atoms, + lengthunit=lengthunit, + velocityunit=velocityunit, + forceunit=forceunit, + timeunit=timeunit, + ) as W: for ts in universe.trajectory: W.write(universe) def test_no_units_w_convert_true(self, universe_no_units, outfile, Writer): # no units + convert_units = ValueError with pytest.raises(ValueError, match="The trajectory has no units,"): - with Writer(outfile, - universe_no_units.atoms.n_atoms) as W: + with Writer(outfile, universe_no_units.atoms.n_atoms) as W: 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) @@ -729,12 +866,11 @@ def test_no_units_w_convert_false(self, universe_no_units, for unit in uw.trajectory.units.values(): assert_equal(unit, None) - @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: + @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: for ts in universe.trajectory: W.write(universe) @@ -744,20 +880,20 @@ def test_convert_units(self, universe, outfile, Writer, 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: + with Writer(outfile, universe.atoms.n_atoms, chunks=chunks) as W: for ts in universe.trajectory: W.write(universe) uw = mda.Universe(TPR_xvf, outfile) - for dset in (uw.trajectory._particle_group['position/value'], - uw.trajectory._particle_group['velocity/value'], - uw.trajectory._particle_group['force/value']): + for dset in ( + uw.trajectory._particle_group["position/value"], + uw.trajectory._particle_group["velocity/value"], + uw.trajectory._particle_group["force/value"], + ): assert_equal(dset.chunks, chunks) for ts1, ts2 in zip(universe.trajectory, uw.trajectory): @@ -768,16 +904,16 @@ def test_write_chunks(self, universe, outfile, Writer, chunks): def test_write_chunks_with_nframes(self, universe, outfile, Writer): n_atoms = universe.atoms.n_atoms n_frames = universe.trajectory.n_frames - with Writer(outfile, - n_atoms=n_atoms, - n_frames=n_frames) as W: + with Writer(outfile, n_atoms=n_atoms, n_frames=n_frames) as W: for ts in universe.trajectory: W.write(universe) uw = mda.Universe(TPR_xvf, outfile) - for dset in (uw.trajectory._particle_group['position/value'], - uw.trajectory._particle_group['velocity/value'], - uw.trajectory._particle_group['force/value']): + for dset in ( + uw.trajectory._particle_group["position/value"], + uw.trajectory._particle_group["velocity/value"], + uw.trajectory._particle_group["force/value"], + ): assert_equal(dset.chunks, (1, n_atoms, 3)) for ts1, ts2 in zip(universe.trajectory, uw.trajectory): @@ -788,55 +924,59 @@ 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) uw = mda.Universe(TPR_xvf, outfile) - for dset in (uw.trajectory._particle_group['position/value'], - uw.trajectory._particle_group['velocity/value'], - uw.trajectory._particle_group['force/value']): + for dset in ( + uw.trajectory._particle_group["position/value"], + uw.trajectory._particle_group["velocity/value"], + uw.trajectory._particle_group["force/value"], + ): assert_equal(dset.chunks, None) def test_write_contiguous2(self, universe, Writer, outfile): - ag = universe.select_atoms('all') + ag = universe.select_atoms("all") n_frames = len(ag.universe.trajectory) - ag.write(outfile, frames='all', n_frames=n_frames, chunks=False) + ag.write(outfile, frames="all", n_frames=n_frames, chunks=False) uw = mda.Universe(TPR_xvf, outfile) - for dset in (uw.trajectory._particle_group['position/value'], - uw.trajectory._particle_group['velocity/value'], - uw.trajectory._particle_group['force/value']): + for dset in ( + uw.trajectory._particle_group["position/value"], + uw.trajectory._particle_group["velocity/value"], + uw.trajectory._particle_group["force/value"], + ): 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): - with Writer(outfile, - universe.atoms.n_atoms, - compression=filter, - compression_opts=opts) as W: + @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, + compression=filter, + compression_opts=opts, + ) as W: for ts in universe.trajectory: W.write(universe) uw = mda.Universe(TPR_xvf, outfile) - dset = uw.trajectory._particle_group['position/value'] + dset = uw.trajectory._particle_group["position/value"] assert_equal(dset.compression, filter) assert_equal(dset.compression_opts, opts) - @pytest.mark.xfail(os.name == 'nt', - reason="occasional PermissionError on windows") - @pytest.mark.parametrize('driver', ('core', 'stdio')) + @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: + with Writer(outfile, universe.atoms.n_atoms, driver=driver) as W: for ts in universe.trajectory: W.write(universe) @@ -844,13 +984,11 @@ def test_write_with_drivers(self, universe, outfile, Writer, driver): file = uw.trajectory._file assert_equal(file.driver, driver) - def test_parallel_disabled(self, universe, Writer, outfile, - driver='mpio'): - with pytest.raises(ValueError, - match="H5MDWriter: parallel writing with MPI I/O "): - with Writer(outfile, - universe.atoms.n_atoms, - driver=driver) as W: + def test_parallel_disabled(self, universe, Writer, outfile, driver="mpio"): + with pytest.raises( + ValueError, match="H5MDWriter: parallel writing with MPI I/O " + ): + with Writer(outfile, universe.atoms.n_atoms, driver=driver) as W: for ts in universe.trajectory: W.write(universe) @@ -870,9 +1008,11 @@ def test_timestep_not_modified_by_writer(self, universe, Writer, outfile): assert_equal( ts._pos, x, - err_msg="Positions in Timestep were modified by writer.") + err_msg="Positions in Timestep were modified by writer.", + ) assert_equal( - ts.time, time, err_msg="Time in Timestep was modified by writer.") + ts.time, time, err_msg="Time in Timestep was modified by writer." + ) class TestH5PYNotInstalled(object): @@ -881,7 +1021,8 @@ class TestH5PYNotInstalled(object): @pytest.fixture(autouse=True) def block_h5py(self, monkeypatch): monkeypatch.setattr( - sys.modules['MDAnalysis.coordinates.H5MD'], 'HAS_H5PY', False) + sys.modules["MDAnalysis.coordinates.H5MD"], "HAS_H5PY", False + ) @pytest.fixture() def Writer(self): @@ -889,7 +1030,7 @@ def Writer(self): @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir) + 'h5md-writer-test.h5md' + return str(tmpdir) + "h5md-writer-test.h5md" def test_reader_no_h5py(self): with pytest.raises(RuntimeError, match="Please install h5py"): @@ -897,10 +1038,10 @@ 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 Writer(outfile, - u.atoms.n_atoms) as W: + 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) @@ -910,7 +1051,7 @@ class TestH5MDReaderWithObservables(object): """Read H5MD file with 'observables/atoms/energy'.""" prec = 3 - ext = 'h5md' + ext = "h5md" def test_read_h5md_issue4598(self): """Read a H5MD file with observables. diff --git a/testsuite/MDAnalysisTests/coordinates/test_lammps.py b/testsuite/MDAnalysisTests/coordinates/test_lammps.py index 39f693c75c..3b203f5bae 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_lammps.py +++ b/testsuite/MDAnalysisTests/coordinates/test_lammps.py @@ -29,25 +29,37 @@ import MDAnalysis as mda from MDAnalysis import NoDataError -from numpy.testing import (assert_equal, assert_allclose) +from numpy.testing import assert_equal, assert_allclose from MDAnalysisTests import make_Universe from MDAnalysisTests.coordinates.reference import ( - RefLAMMPSData, RefLAMMPSDataMini, RefLAMMPSDataDCD, - RefLAMMPSDataAdditionalColumns + RefLAMMPSData, + RefLAMMPSDataMini, + RefLAMMPSDataDCD, + RefLAMMPSDataAdditionalColumns, ) from MDAnalysisTests.datafiles import ( - LAMMPScnt, LAMMPShyd, LAMMPSdata, LAMMPSdata_mini, LAMMPSdata_triclinic, - LAMMPSDUMP, LAMMPSDUMP_allcoords, LAMMPSDUMP_nocoords, LAMMPSDUMP_triclinic, - LAMMPSDUMP_image_vf, LAMMPS_image_vf, LAMMPSdata_additional_columns, - LAMMPSDUMP_additional_columns + LAMMPScnt, + LAMMPShyd, + LAMMPSdata, + LAMMPSdata_mini, + LAMMPSdata_triclinic, + LAMMPSDUMP, + LAMMPSDUMP_allcoords, + LAMMPSDUMP_nocoords, + LAMMPSDUMP_triclinic, + LAMMPSDUMP_image_vf, + LAMMPS_image_vf, + LAMMPSdata_additional_columns, + LAMMPSDUMP_additional_columns, ) def test_datareader_ValueError(): from MDAnalysis.coordinates.LAMMPS import DATAReader + with pytest.raises(ValueError): - DATAReader('filename') + DATAReader("filename") class _TestLammpsData_Coords(object): @@ -56,7 +68,7 @@ class _TestLammpsData_Coords(object): All topology loading from MDAnalysisTests.data is done in test_topology """ - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def u(self): return mda.Universe(self.filename) @@ -97,17 +109,20 @@ class TestLammpsDataMini_Coords(_TestLammpsData_Coords, RefLAMMPSDataMini): pass -@pytest.fixture(params=[ - LAMMPSdata, - LAMMPSdata_mini, - LAMMPScnt, - LAMMPShyd, -], scope='module') +@pytest.fixture( + params=[ + LAMMPSdata, + LAMMPSdata_mini, + LAMMPScnt, + LAMMPShyd, + ], + scope="module", +) def LAMMPSDATAWriter(request, tmpdir_factory): filename = request.param u = mda.Universe(filename) fn = os.path.split(filename)[1] - outfile = str(tmpdir_factory.mktemp('data').join(fn)) + outfile = str(tmpdir_factory.mktemp("data").join(fn)) with mda.Writer(outfile, n_atoms=u.atoms.n_atoms) as w: w.write(u.atoms) @@ -117,23 +132,26 @@ def LAMMPSDATAWriter(request, tmpdir_factory): return u, u_new -@pytest.fixture(params=[ - [LAMMPSdata, True], - [LAMMPSdata_mini, True], - [LAMMPScnt, True], - [LAMMPShyd, True], - [LAMMPSdata, False] -], scope='module') +@pytest.fixture( + params=[ + [LAMMPSdata, True], + [LAMMPSdata_mini, True], + [LAMMPScnt, True], + [LAMMPShyd, True], + [LAMMPSdata, False], + ], + scope="module", +) def LAMMPSDATAWriter_molecule_tag(request, tmpdir_factory): filename, charges = request.param u = mda.Universe(filename) if not charges: - u.del_TopologyAttr('charges') + u.del_TopologyAttr("charges") - u.trajectory.ts.data['molecule_tag'] = u.atoms.resids + u.trajectory.ts.data["molecule_tag"] = u.atoms.resids fn = os.path.split(filename)[1] - outfile = str(tmpdir_factory.mktemp('data').join(fn)) + outfile = str(tmpdir_factory.mktemp("data").join(fn)) with mda.Writer(outfile, n_atoms=u.atoms.n_atoms) as w: w.write(u.atoms) @@ -145,84 +163,106 @@ def LAMMPSDATAWriter_molecule_tag(request, tmpdir_factory): def test_unwrap_vel_force(): - u_wrapped = mda.Universe(LAMMPS_image_vf, [LAMMPSDUMP_image_vf], - format="LAMMPSDUMP") + u_wrapped = mda.Universe( + LAMMPS_image_vf, [LAMMPSDUMP_image_vf], format="LAMMPSDUMP" + ) u_wrapped.trajectory[-1] - - assert_allclose(u_wrapped.atoms.positions[0], - np.array([2.56616, 6.11565, 7.37956]), - atol=1e-5) + + assert_allclose( + u_wrapped.atoms.positions[0], + np.array([2.56616, 6.11565, 7.37956]), + atol=1e-5, + ) assert hasattr(u_wrapped.atoms, "velocities") assert hasattr(u_wrapped.atoms, "forces") def test_unwrap_image_wrap(): - u_unwrapped = mda.Universe(LAMMPS_image_vf, LAMMPSDUMP_image_vf, - format="LAMMPSDUMP", unwrap_images=True) + u_unwrapped = mda.Universe( + LAMMPS_image_vf, + LAMMPSDUMP_image_vf, + format="LAMMPSDUMP", + unwrap_images=True, + ) u_unwrapped.trajectory[-1] - pos = (np.array([2.56616, 6.11565, 7.37956]) + - np.array([3, 1, -4])*u_unwrapped.dimensions[:3]) - assert_allclose(u_unwrapped.atoms.positions[0], - pos, - atol=1e-5, - ) + pos = ( + np.array([2.56616, 6.11565, 7.37956]) + + np.array([3, 1, -4]) * u_unwrapped.dimensions[:3] + ) + assert_allclose( + u_unwrapped.atoms.positions[0], + pos, + atol=1e-5, + ) def test_unwrap_no_image(): with pytest.raises(ValueError, match="must have image flag"): - u_unwrapped = mda.Universe( - LAMMPSDUMP_allcoords, - format="LAMMPSDUMP", - unwrap_images=True) + u_unwrapped = mda.Universe( + LAMMPSDUMP_allcoords, format="LAMMPSDUMP", unwrap_images=True + ) class TestLAMMPSDATAWriter(object): def test_Writer_dimensions(self, LAMMPSDATAWriter): u_ref, u_new = LAMMPSDATAWriter - assert_allclose(u_ref.dimensions, u_new.dimensions, - err_msg="attributes different after writing", - atol=1e-6) + assert_allclose( + u_ref.dimensions, + u_new.dimensions, + err_msg="attributes different after writing", + atol=1e-6, + ) def test_Writer_atoms_types(self, LAMMPSDATAWriter): u_ref, u_new = LAMMPSDATAWriter - assert_equal(u_ref.atoms.types, u_new.atoms.types, - err_msg="attributes different after writing",) - - @pytest.mark.parametrize('attr', [ - 'bonds', 'angles', 'dihedrals', 'impropers' - ]) + assert_equal( + u_ref.atoms.types, + u_new.atoms.types, + err_msg="attributes different after writing", + ) + + @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: refvals = getattr(u_ref, attr) - except (AttributeError): + except AttributeError: with pytest.raises(AttributeError): getattr(u_new, attr) else: - assert_allclose(refvals, - getattr(u_new.atoms, attr), - err_msg="attributes different after writing", - atol=1e-6) + assert_allclose( + refvals, + getattr(u_new.atoms, attr), + err_msg="attributes different after writing", + atol=1e-6, + ) class TestLAMMPSDATAWriter_molecule_tag(object): def test_molecule_tag(self, LAMMPSDATAWriter_molecule_tag): u_ref, u_new = LAMMPSDATAWriter_molecule_tag - assert_equal(u_ref.atoms.resids, u_new.atoms.resids, - err_msg="resids different after writing",) + assert_equal( + u_ref.atoms.resids, + u_new.atoms.resids, + err_msg="resids different after writing", + ) -@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 @@ -251,7 +291,7 @@ def LAMMPSDATA_partial(tmpdir): N_kept = 5 u = mda.Universe(filename) ext = os.path.splitext(filename)[1] - outfile = str(tmpdir.join('lammps-data-writer-test' + ext)) + outfile = str(tmpdir.join("lammps-data-writer-test" + ext)) with mda.Writer(outfile, n_atoms=N_kept) as w: w.write(u.atoms[:N_kept]) @@ -260,16 +300,18 @@ 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): - assert_allclose(getattr(u_ref.atoms[:self.N_kept], attr), - getattr(u_new.atoms, attr), - err_msg="attributes different after writing", - atol=1e-6) + assert_allclose( + getattr(u_ref.atoms[: self.N_kept], attr), + getattr(u_new.atoms, attr), + err_msg="attributes different after writing", + atol=1e-6, + ) else: with pytest.raises(AttributeError): getattr(u_new, attr) @@ -285,13 +327,13 @@ def test_n_angles(self, LAMMPSDATA_partial): # need more tests of the LAMMPS DCDReader + class TestLAMMPSDCDReader(RefLAMMPSDataDCD): - flavor = 'LAMMPS' + flavor = "LAMMPS" - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def u(self): - return mda.Universe(self.topology, self.trajectory, - format=self.format) + return mda.Universe(self.topology, self.trajectory, format=self.format) def test_Reader_is_LAMMPS(self, u): assert u.trajectory.flavor, self.flavor @@ -308,91 +350,113 @@ 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): - assert_allclose(u.trajectory.dt, self.dt, - err_msg="Time between frames dt is wrong.") + assert_allclose( + u.trajectory.dt, + self.dt, + err_msg="Time between frames dt is wrong.", + ) def test_Timestep_time(self, u): iframe = self.get_frame_from_end(1, u) - assert_allclose(u.trajectory[iframe].time, - 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.): - u = mda.Universe(self.topology, self.trajectory, format=self.format, - dt=dt) + assert_allclose( + u.trajectory[iframe].time, + 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 + ) iframe = self.get_frame_from_end(1, u) - assert_allclose(u.trajectory[iframe].time, iframe * dt, - err_msg="setting time step dt={0} failed: " - "actually used dt={1}".format( - dt, u.trajectory._ts_kwargs['dt'])) + assert_allclose( + u.trajectory[iframe].time, + iframe * dt, + err_msg="setting time step dt={0} failed: " + "actually used dt={1}".format(dt, u.trajectory._ts_kwargs["dt"]), + ) def test_wrong_time_unit(self): def wrong_load(unit="nm"): - return mda.Universe(self.topology, self.trajectory, - format=self.format, - timeunit=unit) + return mda.Universe( + self.topology, + self.trajectory, + format=self.format, + timeunit=unit, + ) with pytest.raises(TypeError): wrong_load() def test_wrong_unit(self): def wrong_load(unit="GARBAGE"): - return mda.Universe(self.topology, self.trajectory, - format=self.format, - timeunit=unit) + return mda.Universe( + self.topology, + self.trajectory, + format=self.format, + timeunit=unit, + ) with pytest.raises(ValueError): wrong_load() class TestLAMMPSDCDWriter(RefLAMMPSDataDCD): - flavor = 'LAMMPS' + flavor = "LAMMPS" - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def u(self): return mda.Universe(self.topology, self.trajectory, format=self.format) 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: + outfile = str(tmpdir.join("lammps-writer-test" + ext)) + 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)) + 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) short = mda.Universe(self.topology, outfile) - assert_equal(short.trajectory.n_frames, n_frames, - err_msg="number of frames mismatch") - assert_allclose(short.trajectory[n_frames - 1].positions, - u.trajectory[n_frames - 1].positions, - 6, - err_msg="coordinate mismatch between corresponding frames") + assert_equal( + short.trajectory.n_frames, + n_frames, + err_msg="number of frames mismatch", + ) + assert_allclose( + short.trajectory[n_frames - 1].positions, + u.trajectory[n_frames - 1].positions, + 6, + err_msg="coordinate mismatch between corresponding frames", + ) def test_OtherWriter_is_LAMMPS(self, u, tmpdir): ext = os.path.splitext(self.trajectory)[1] - outfile = str(tmpdir.join('lammps-writer-test' + ext)) + outfile = str(tmpdir.join("lammps-writer-test" + ext)) with u.trajectory.OtherWriter(outfile) as W: assert W.flavor, self.flavor def test_OtherWriter(self, u, tmpdir): times = [] ext = os.path.splitext(self.trajectory)[1] - outfile = str(tmpdir.join('lammps-writer-test' + ext)) + outfile = str(tmpdir.join("lammps-writer-test" + ext)) with u.trajectory.OtherWriter(outfile) as w: for ts in u.trajectory[::-1]: times.append(ts.time) @@ -403,27 +467,36 @@ def test_OtherWriter(self, u, tmpdir): # but DCD has no way to store timestamps. Right now, we'll simply # test that this is the case and pass. reversed = mda.Universe(self.topology, outfile) - assert_equal(reversed.trajectory.n_frames, u.trajectory.n_frames, - err_msg="number of frames mismatch") + assert_equal( + reversed.trajectory.n_frames, + u.trajectory.n_frames, + err_msg="number of frames mismatch", + ) rev_times = [ts.time for ts in reversed.trajectory] - assert_allclose(rev_times, times[::-1], 6, - err_msg="time steps of written DCD mismatch") - assert_allclose(reversed.trajectory[-1].positions, - u.trajectory[0].positions, - 6, - err_msg="coordinate mismatch between corresponding frames") + assert_allclose( + rev_times, + times[::-1], + 6, + err_msg="time steps of written DCD mismatch", + ) + assert_allclose( + reversed.trajectory[-1].positions, + u.trajectory[0].positions, + 6, + err_msg="coordinate mismatch between corresponding frames", + ) class TestLAMMPSDCDWriterClass(object): - flavor = 'LAMMPS' + flavor = "LAMMPS" def test_Writer_is_LAMMPS(self, tmpdir): - outfile = str(tmpdir.join('lammps-writer-test.dcd')) + outfile = str(tmpdir.join("lammps-writer-test.dcd")) with mda.coordinates.LAMMPS.DCDWriter(outfile, n_atoms=10) as W: assert W.flavor, self.flavor def test_open(self, tmpdir): - outfile = str(tmpdir.join('lammps-writer-test.dcd')) + outfile = str(tmpdir.join("lammps-writer-test.dcd")) try: with mda.coordinates.LAMMPS.DCDWriter(outfile, n_atoms=10): pass @@ -431,127 +504,148 @@ def test_open(self, tmpdir): pytest.fail() def test_wrong_time_unit(self, tmpdir): - outfile = str(tmpdir.join('lammps-writer-test.dcd')) + 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): - outfile = str(tmpdir.join('lammps-writer-test.dcd')) + outfile = str(tmpdir.join("lammps-writer-test.dcd")) with pytest.raises(ValueError): - with mda.coordinates.LAMMPS.DCDWriter(outfile, n_atoms=10, - timeunit='GARBAGE'): + with mda.coordinates.LAMMPS.DCDWriter( + outfile, n_atoms=10, timeunit="GARBAGE" + ): pass def test_triclinicness(): u = mda.Universe(LAMMPScnt) - assert u.dimensions[3] == 90. - assert u.dimensions[4] == 90. - assert u.dimensions[5] == 120. + assert u.dimensions[3] == 90.0 + assert u.dimensions[4] == 90.0 + assert u.dimensions[5] == 120.0 @pytest.fixture def tmpout(tmpdir): - return str(tmpdir.join('out.data')) + return str(tmpdir.join("out.data")) class TestDataWriterErrors(object): def test_write_no_masses(self, tmpout): - u = make_Universe(('types',), trajectory=True) + u = make_Universe(("types",), trajectory=True) try: u.atoms.write(tmpout) except NoDataError as e: - assert 'masses' in e.args[0] + assert "masses" in e.args[0] else: pytest.fail() def test_write_no_types(self, tmpout): - u = make_Universe(('masses',), trajectory=True) + u = make_Universe(("masses",), trajectory=True) try: u.atoms.write(tmpout) except NoDataError as e: - assert 'types' in e.args[0] + assert "types" in e.args[0] else: pytest.fail() def test_write_non_numerical_types(self, tmpout): - u = make_Universe(('types', 'masses'), trajectory=True) + u = make_Universe(("types", "masses"), trajectory=True) try: u.atoms.write(tmpout) except ValueError as e: - assert 'must be convertible to integers' in e.args[0] + assert "must be convertible to integers" in e.args[0] else: raise pytest.fail() class TestLammpsDumpReader(object): - @pytest.fixture( - params=['ascii', 'bz2', 'gzip'] - ) + @pytest.fixture(params=["ascii", "bz2", "gzip"]) def u(self, tmpdir, request): trjtype = request.param - if trjtype == 'bz2': + if trjtype == "bz2": # no conversion needed f = LAMMPSDUMP else: - f = str(tmpdir.join('lammps.' + trjtype)) - with bz2.BZ2File(LAMMPSDUMP, 'rb') as datain: + f = str(tmpdir.join("lammps." + trjtype)) + with bz2.BZ2File(LAMMPSDUMP, "rb") as datain: data = datain.read() - if trjtype == 'ascii': - with open(f, 'wb') as fout: + if trjtype == "ascii": + with open(f, "wb") as fout: fout.write(data) - elif trjtype == 'gzip': - with gzip.GzipFile(f, 'wb') as fout: + elif trjtype == "gzip": + 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): f = LAMMPSDUMP_additional_columns top = LAMMPSdata_additional_columns - return mda.Universe(top, f, format='LAMMPSDUMP', - lammps_coordinate_convention="auto", - additional_columns=True) + return mda.Universe( + top, + f, + format="LAMMPSDUMP", + lammps_coordinate_convention="auto", + additional_columns=True, + ) @pytest.fixture() def u_additional_columns_single(self): f = LAMMPSDUMP_additional_columns top = LAMMPSdata_additional_columns - return mda.Universe(top, f, format='LAMMPSDUMP', - lammps_coordinate_convention="auto", - additional_columns=['q']) + return mda.Universe( + top, + f, + format="LAMMPSDUMP", + lammps_coordinate_convention="auto", + additional_columns=["q"], + ) @pytest.fixture() def u_additional_columns_multiple(self): f = LAMMPSDUMP_additional_columns top = LAMMPSdata_additional_columns - return mda.Universe(top, f, format='LAMMPSDUMP', - lammps_coordinate_convention="auto", - additional_columns=['q', 'p']) + return mda.Universe( + top, + f, + format="LAMMPSDUMP", + lammps_coordinate_convention="auto", + additional_columns=["q", "p"], + ) @pytest.fixture() def u_additional_columns_wrong_format(self): f = LAMMPSDUMP_additional_columns top = LAMMPSdata_additional_columns - return mda.Universe(top, f, format='LAMMPSDUMP', - lammps_coordinate_convention="auto", - additional_columns='q') + return mda.Universe( + top, + f, + format="LAMMPSDUMP", + lammps_coordinate_convention="auto", + additional_columns="q", + ) @pytest.fixture() def u_additional_columns_not_present(self): f = LAMMPSDUMP_additional_columns top = LAMMPSdata_additional_columns - return mda.Universe(top, f, format='LAMMPSDUMP', - lammps_coordinate_convention="auto", - additional_columns=['q', 'w']) + return mda.Universe( + top, + f, + format="LAMMPSDUMP", + lammps_coordinate_convention="auto", + additional_columns=["q", "w"], + ) @pytest.fixture() def reference_positions(self): @@ -559,19 +653,19 @@ def reference_positions(self): data = {} # at timestep 500 - lo, hi = float(2.1427867124774069e-01), float(5.9857213287522608e+00) + lo, hi = float(2.1427867124774069e-01), float(5.9857213287522608e00) length1 = hi - lo # at timestep 1000 - lo, hi = float(-5.4458069063278991e-03), float(6.2054458069063330e+00) + lo, hi = float(-5.4458069063278991e-03), float(6.2054458069063330e00) length2 = hi - lo boxes = [ - np.array([6.2, 6.2, 6.2, 90., 90., 90.]), - np.array([length1, length1, length1, 90., 90., 90.]), - np.array([length2, length2, length2, 90., 90., 90.]), + np.array([6.2, 6.2, 6.2, 90.0, 90.0, 90.0]), + np.array([length1, length1, length1, 90.0, 90.0, 90.0]), + np.array([length2, length2, length2, 90.0, 90.0, 90.0]), ] - data['box'] = boxes + data["box"] = boxes box_mins = [ - np.array([0., 0., 0.]), + np.array([0.0, 0.0, 0.0]), np.array([0.21427867, 0.21427867, 0.21427867]), np.array([-0.00544581, -0.00544581, -0.00544581]), ] @@ -582,14 +676,14 @@ def reference_positions(self): atom1_pos1 = np.array([0.25, 0.25, 0.241936]) * boxes[0][:3] atom1_pos2 = np.array([0.278215, 0.12611, 0.322087]) * boxes[1][:3] atom1_pos3 = np.array([0.507123, 1.00424, 0.280972]) * boxes[2][:3] - data['atom1_pos'] = [atom1_pos1, atom1_pos2, atom1_pos3] + data["atom1_pos"] = [atom1_pos1, atom1_pos2, atom1_pos3] # data for atom id 13 # *is* sensitive to reordering of positions # normally appears 4th in traj data atom13_pos1 = np.array([0.25, 0.25, 0.741936]) * boxes[0][:3] atom13_pos2 = np.array([0.394618, 0.263115, 0.798295]) * boxes[1][:3] atom13_pos3 = np.array([0.332363, 0.30544, 0.641589]) * boxes[2][:3] - data['atom13_pos'] = [atom13_pos1, atom13_pos2, atom13_pos3] + data["atom13_pos"] = [atom13_pos1, atom13_pos2, atom13_pos3] return data @@ -600,106 +694,146 @@ def test_length(self, u): assert len(u.trajectory) == 3 for i, ts in enumerate(u.trajectory): assert ts.frame == i - assert ts.data['step'] == i * 500 + assert ts.data["step"] == i * 500 for i, ts in enumerate(u.trajectory): assert ts.frame == i - assert ts.data['step'] == i * 500 + assert ts.data["step"] == i * 500 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]) - assert_allclose(u.atoms[0].position, pos, - atol=1e-5) - pos = (reference_positions['atom13_pos'][1] - - reference_positions['mins'][1]) - assert_allclose(u.atoms[12].position, pos, - atol=1e-5) + assert_allclose(u.dimensions, reference_positions["box"][1], atol=1e-5) + 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] + ) + assert_allclose(u.atoms[12].position, pos, atol=1e-5) def test_boxsize(self, u, reference_positions): - for ts, box in zip(u.trajectory, - reference_positions['box']): + for ts, box in zip(u.trajectory, reference_positions["box"]): assert_allclose(ts.dimensions, box, atol=1e-5) def test_atom_reordering(self, u, reference_positions): atom1 = u.atoms[0] atom13 = u.atoms[12] - for ts, atom1_pos, atom13_pos, bmin in zip(u.trajectory, - reference_positions['atom1_pos'], - reference_positions['atom13_pos'], - reference_positions['mins']): - assert_allclose(atom1.position, atom1_pos-bmin, atol=1e-5) - assert_allclose(atom13.position, atom13_pos-bmin, atol=1e-5) - - @pytest.mark.parametrize("system, fields", [ - ('u_additional_columns_true', ['q', 'p']), - ('u_additional_columns_single', ['q']), - ('u_additional_columns_multiple', ['q', 'p']), - ]) + for ts, atom1_pos, atom13_pos, bmin in zip( + u.trajectory, + reference_positions["atom1_pos"], + reference_positions["atom13_pos"], + reference_positions["mins"], + ): + assert_allclose(atom1.position, atom1_pos - bmin, atol=1e-5) + assert_allclose(atom13.position, atom13_pos - bmin, atol=1e-5) + + @pytest.mark.parametrize( + "system, fields", + [ + ("u_additional_columns_true", ["q", "p"]), + ("u_additional_columns_single", ["q"]), + ("u_additional_columns_multiple", ["q", "p"]), + ], + ) 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)) - - @pytest.mark.parametrize("system", [ - ('u_additional_columns_wrong_format'), - ]) + assert_allclose( + data, getattr(RefLAMMPSDataAdditionalColumns, field) + ) + + @pytest.mark.parametrize( + "system", + [ + ("u_additional_columns_wrong_format"), + ], + ) 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("system", [ - ('u_additional_columns_not_present'), - ]) + @pytest.mark.parametrize( + "system", + [ + ("u_additional_columns_not_present"), + ], + ) def test_warning(self, system, request): with pytest.warns(match="Some of the additional"): 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(LAMMPSDUMP, format='LAMMPSDUMP', - lammps_coordinate_convention=convention) + mda.Universe( + LAMMPSDUMP, + format="LAMMPSDUMP", + lammps_coordinate_convention=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") - - -@pytest.mark.parametrize("convention,result", - [("auto", "unscaled"), ("unscaled", "unscaled"), - ("scaled", "scaled"), ("unwrapped", "unwrapped"), - ("scaled_unwrapped", "scaled_unwrapped")]) + with pytest.raises(ValueError, match="is not a valid option"): + mda.Universe( + LAMMPSDUMP, format="LAMMPSDUMP", lammps_coordinate_convention="42" + ) + + +@pytest.mark.parametrize( + "convention,result", + [ + ("auto", "unscaled"), + ("unscaled", "unscaled"), + ("scaled", "scaled"), + ("unwrapped", "unwrapped"), + ("scaled_unwrapped", "scaled_unwrapped"), + ], +) def test_open_all_convention(convention, result): - u = mda.Universe(LAMMPSDUMP_allcoords, format='LAMMPSDUMP', - lammps_coordinate_convention=convention) - assert(u.trajectory.lammps_coordinate_convention == result) + u = mda.Universe( + LAMMPSDUMP_allcoords, + format="LAMMPSDUMP", + lammps_coordinate_convention=convention, + ) + assert u.trajectory.lammps_coordinate_convention == result def test_no_coordinate_info(): with pytest.raises(ValueError, match="No coordinate information detected"): - u = mda.Universe(LAMMPSDUMP_nocoords, format='LAMMPSDUMP', - lammps_coordinate_convention="auto") + u = mda.Universe( + LAMMPSDUMP_nocoords, + format="LAMMPSDUMP", + lammps_coordinate_convention="auto", + ) class TestCoordinateMatches(object): @pytest.fixture() def universes(self): - coordinate_conventions = ["auto", "unscaled", "scaled", "unwrapped", - "scaled_unwrapped"] - universes = {i: mda.Universe(LAMMPSDUMP_allcoords, format='LAMMPSDUMP', - lammps_coordinate_convention=i) - for i in coordinate_conventions} + coordinate_conventions = [ + "auto", + "unscaled", + "scaled", + "unwrapped", + "scaled_unwrapped", + ] + universes = { + i: mda.Universe( + LAMMPSDUMP_allcoords, + format="LAMMPSDUMP", + lammps_coordinate_convention=i, + ) + for i in coordinate_conventions + } return universes @pytest.fixture() @@ -710,21 +844,32 @@ def reference_unscaled_positions(self): atom340_pos1_unscaled = np.array([4.48355, 0.331422, 1.59231]) - bmin atom340_pos2_unscaled = np.array([4.41947, 35.4403, 2.25115]) - bmin atom340_pos3_unscaled = np.array([4.48989, 0.360633, 2.63623]) - bmin - return np.asarray([atom340_pos1_unscaled, atom340_pos2_unscaled, - atom340_pos3_unscaled]) + return np.asarray( + [ + atom340_pos1_unscaled, + atom340_pos2_unscaled, + atom340_pos3_unscaled, + ] + ) def test_unscaled_reference(self, universes, reference_unscaled_positions): atom_340 = universes["unscaled"].atoms[339] for i, ts_u in enumerate(universes["unscaled"].trajectory[0:3]): - assert_allclose(atom_340.position, - reference_unscaled_positions[i, :], atol=1e-5) + assert_allclose( + atom_340.position, + reference_unscaled_positions[i, :], + atol=1e-5, + ) def test_scaled_reference(self, universes, reference_unscaled_positions): # NOTE use of unscaled positions here due to S->R transform atom_340 = universes["scaled"].atoms[339] for i, ts_u in enumerate(universes["scaled"].trajectory[0:3]): - assert_allclose(atom_340.position, - reference_unscaled_positions[i, :], atol=1e-1) + assert_allclose( + atom_340.position, + reference_unscaled_positions[i, :], + atol=1e-1, + ) # NOTE this seems a bit inaccurate? @pytest.fixture() @@ -734,60 +879,85 @@ def reference_unwrapped_positions(self): atom340_pos1_unwrapped = [4.48355, 35.8378, 1.59231] atom340_pos2_unwrapped = [4.41947, 35.4403, 2.25115] atom340_pos3_unwrapped = [4.48989, 35.867, 2.63623] - return np.asarray([atom340_pos1_unwrapped, atom340_pos2_unwrapped, - atom340_pos3_unwrapped]) - - def test_unwrapped_scaled_reference(self, universes, - reference_unwrapped_positions): + return np.asarray( + [ + atom340_pos1_unwrapped, + atom340_pos2_unwrapped, + atom340_pos3_unwrapped, + ] + ) + + 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(atom_340.position, - reference_unwrapped_positions[i, :], atol=1e-5) - - def test_unwrapped_scaled_reference(self, universes, - reference_unwrapped_positions): + assert_allclose( + atom_340.position, + reference_unwrapped_positions[i, :], + atol=1e-5, + ) + + 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]): - assert_allclose(atom_340.position, - reference_unwrapped_positions[i, :], atol=1e-1) + universes["scaled_unwrapped"].trajectory[0:3] + ): + assert_allclose( + atom_340.position, + reference_unwrapped_positions[i, :], + atol=1e-1, + ) # NOTE this seems a bit inaccurate? def test_scaled_unscaled_match(self, universes): - assert(len(universes["unscaled"].trajectory) - == len(universes["scaled"].trajectory)) - for ts_u, ts_s in zip(universes["unscaled"].trajectory, - universes["scaled"].trajectory): + assert len(universes["unscaled"].trajectory) == len( + universes["scaled"].trajectory + ) + for ts_u, ts_s in zip( + universes["unscaled"].trajectory, universes["scaled"].trajectory + ): assert_allclose(ts_u.positions, ts_s.positions, atol=1e-1) # NOTE this seems a bit inaccurate? def test_unwrapped_scaled_unwrapped_match(self, universes): - assert(len(universes["unwrapped"].trajectory) == - len(universes["scaled_unwrapped"].trajectory)) - for ts_u, ts_s in zip(universes["unwrapped"].trajectory, - universes["scaled_unwrapped"].trajectory): + assert len(universes["unwrapped"].trajectory) == len( + universes["scaled_unwrapped"].trajectory + ) + for ts_u, ts_s in zip( + universes["unwrapped"].trajectory, + universes["scaled_unwrapped"].trajectory, + ): assert_allclose(ts_u.positions, ts_s.positions, atol=1e-1) # NOTE this seems a bit inaccurate? def test_auto_is_unscaled_match(self, universes): - assert(len(universes["auto"].trajectory) == - len(universes["unscaled"].trajectory)) - for ts_a, ts_s in zip(universes["auto"].trajectory, - universes["unscaled"].trajectory): + assert len(universes["auto"].trajectory) == len( + universes["unscaled"].trajectory + ) + for ts_a, ts_s in zip( + universes["auto"].trajectory, universes["unscaled"].trajectory + ): assert_allclose(ts_a.positions, ts_s.positions, atol=1e-5) class TestLammpsTriclinic(object): @pytest.fixture() def u_dump(self): - return mda.Universe(LAMMPSDUMP_triclinic, format='LAMMPSDUMP', - lammps_coordinate_convention="auto") + return mda.Universe( + LAMMPSDUMP_triclinic, + format="LAMMPSDUMP", + lammps_coordinate_convention="auto", + ) @pytest.fixture() def u_data(self): - return mda.Universe(LAMMPSdata_triclinic, format='data', - atom_style='id type x y z') + return mda.Universe( + LAMMPSdata_triclinic, format="data", atom_style="id type x y z" + ) @pytest.fixture() def reference_box(self): @@ -815,7 +985,8 @@ 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 223345de15..5d020d43d2 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_memory.py +++ b/testsuite/MDAnalysisTests/coordinates/test_memory.py @@ -26,8 +26,10 @@ import pytest from MDAnalysis.coordinates.memory import MemoryReader from MDAnalysisTests.datafiles import DCD, PSF -from MDAnalysisTests.coordinates.base import (BaseReference, - MultiframeReaderTest) +from MDAnalysisTests.coordinates.base import ( + BaseReference, + MultiframeReaderTest, +) from MDAnalysis.coordinates.memory import Timestep from numpy.testing import assert_equal, assert_almost_equal @@ -51,27 +53,29 @@ def __init__(self): self.first_frame = Timestep(self.n_atoms) self.first_frame.positions = np.array(self.universe.trajectory[0]) self.first_frame.frame = 0 - self.first_frame.time = self.first_frame.frame*self.dt + self.first_frame.time = self.first_frame.frame * self.dt self.second_frame = Timestep(self.n_atoms) self.second_frame.positions = np.array(self.universe.trajectory[1]) self.second_frame.frame = 1 - self.second_frame.time = self.second_frame.frame*self.dt + self.second_frame.time = self.second_frame.frame * self.dt self.last_frame = Timestep(self.n_atoms) - self.last_frame.positions = \ - np.array(self.universe.trajectory[self.n_frames - 1]) + self.last_frame.positions = np.array( + self.universe.trajectory[self.n_frames - 1] + ) self.last_frame.frame = self.n_frames - 1 - self.last_frame.time = self.last_frame.frame*self.dt + self.last_frame.time = self.last_frame.frame * self.dt self.jump_to_frame = self.first_frame.copy() self.jump_to_frame.positions = np.array(self.universe.trajectory[3]) self.jump_to_frame.frame = 3 - self.jump_to_frame.time = self.jump_to_frame.frame*self.dt + 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] @@ -82,7 +86,7 @@ def iter_ts(self, i): class TestMemoryReader(MultiframeReaderTest): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def ref(): return MemoryReference() @@ -96,14 +100,18 @@ 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): universe1 = mda.Universe(PSF, DCD, in_memory=True) - universe2 = mda.Universe(PSF, DCD, in_memory=True, order='fac') - assert_equal(universe1.trajectory.get_array().shape, - universe2.trajectory.get_array().shape) + universe2 = mda.Universe(PSF, DCD, in_memory=True, order="fac") + assert_equal( + universe1.trajectory.get_array().shape, + universe2.trajectory.get_array().shape, + ) def test_iteration(self, ref, reader): frames = 0 @@ -111,35 +119,36 @@ def test_iteration(self, ref, reader): frames += 1 assert frames == ref.n_frames - def test_extract_array_afc(self,reader): - assert_equal(reader.timeseries(order='afc').shape, (3341, 98, 3)) + def test_extract_array_afc(self, reader): + assert_equal(reader.timeseries(order="afc").shape, (3341, 98, 3)) def test_extract_array_afc(self, reader): - assert_equal(reader.timeseries(order='afc').shape, (3341, 98, 3)) + assert_equal(reader.timeseries(order="afc").shape, (3341, 98, 3)) def test_extract_array_fac(self, reader): - assert_equal(reader.timeseries(order='fac').shape, (98, 3341, 3)) + assert_equal(reader.timeseries(order="fac").shape, (98, 3341, 3)) def test_extract_array_cfa(self, reader): - assert_equal(reader.timeseries(order='cfa').shape, (3, 98, 3341)) + assert_equal(reader.timeseries(order="cfa").shape, (3, 98, 3341)) def test_extract_array_acf(self, reader): - assert_equal(reader.timeseries(order='acf').shape, (3341, 3, 98)) + assert_equal(reader.timeseries(order="acf").shape, (3341, 3, 98)) def test_extract_array_fca(self, reader): - assert_equal(reader.timeseries(order='fca').shape, (98, 3, 3341)) + assert_equal(reader.timeseries(order="fca").shape, (98, 3, 3341)) def test_extract_array_caf(self, reader): - assert_equal(reader.timeseries(order='caf').shape, (3, 3341, 98)) + 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 array1 = reader.timeseries(step=10) - array2 = reader.timeseries()[:,::10,:] + array2 = reader.timeseries()[:, ::10, :] assert_equal(array1, array2) def test_timeseries_view(self, reader): @@ -150,8 +159,10 @@ def test_timeseries_subarray_view(self, reader): # timeseries() is expected to provide a view of the underlying array # also in the case where we slice the array using the start, stop and # step options. - assert reader.timeseries(start=5,stop=15,step=2,order='fac').base is\ - reader.get_array() + assert ( + reader.timeseries(start=5, stop=15, step=2, order="fac").base + is reader.get_array() + ) def test_timeseries_view_from_universe_atoms(self, ref, reader): # timeseries() is expected to provide a view of the underlying array @@ -163,9 +174,9 @@ 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 @@ -186,9 +197,15 @@ def test_get_writer_2(self): def test_float32(self, ref): # Check that we get float32 positions even when initializing with float64 - 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')) + 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") + ) def test_position_assignation(self, reader): # When coordinates are assigned to a timestep, is the change persistent? @@ -198,19 +215,20 @@ def test_position_assignation(self, reader): assert_almost_equal(reader.ts.positions, new_positions) def test_timeseries_warns_deprecation(self, reader): - with pytest.warns(DeprecationWarning, match="MemoryReader.timeseries " - "inclusive"): + with pytest.warns( + DeprecationWarning, match="MemoryReader.timeseries " "inclusive" + ): reader.timeseries(start=0, stop=3, step=1) def test_timeseries_asel_warns_deprecation(self, ref, reader): selection = ref.universe.atoms with pytest.warns(DeprecationWarning, match="asel argument to"): reader.timeseries(asel=selection) - + def test_timeseries_atomgroup(self, ref, reader): selection = ref.universe.atoms reader.timeseries(atomgroup=selection) - + def test_timeseries_atomgroup_asel_mutex(self, ref, reader): selection = ref.universe.atoms with pytest.raises(ValueError, match="Cannot provide both"): @@ -219,27 +237,27 @@ def test_timeseries_atomgroup_asel_mutex(self, ref, reader): class TestMemoryReaderVelsForces(object): @staticmethod - @pytest.fixture(params=['2d', '3d']) + @pytest.fixture(params=["2d", "3d"]) def ref_pos(request): - if request.param == '2d': + if request.param == "2d": return np.arange(30).reshape(10, 3) - elif request.param == '3d': + elif request.param == "3d": return np.arange(30).reshape(1, 10, 3) @staticmethod - @pytest.fixture(params=['2d', '3d']) + @pytest.fixture(params=["2d", "3d"]) def ref_vels(request): - if request.param == '2d': + if request.param == "2d": return np.arange(30).reshape(10, 3) + 100 - elif request.param == '3d': + elif request.param == "3d": return np.arange(30).reshape(1, 10, 3) + 100 @staticmethod - @pytest.fixture(params=['2d', '3d']) + @pytest.fixture(params=["2d", "3d"]) def ref_forces(request): - if request.param == '2d': + if request.param == "2d": return np.arange(30).reshape(10, 3) + 1000 - elif request.param == '3d': + elif request.param == "3d": return np.arange(30).reshape(1, 10, 3) + 1000 @staticmethod @@ -250,31 +268,27 @@ def assert_equal_dims(arr1, arr2): assert_equal(arr1, arr2) def test_velocities(self, ref_pos, ref_vels): - mr = MemoryReader(ref_pos, - velocities=ref_vels) + mr = MemoryReader(ref_pos, velocities=ref_vels) assert mr.ts.has_velocities self.assert_equal_dims(mr.ts.velocities, ref_vels) assert not mr.ts.has_forces def test_forces(self, ref_pos, ref_forces): - mr = MemoryReader(ref_pos, - forces=ref_forces) + mr = MemoryReader(ref_pos, forces=ref_forces) assert not mr.ts.has_velocities assert mr.ts.has_forces self.assert_equal_dims(mr.ts.forces, ref_forces) def test_both(self, ref_pos, ref_vels, ref_forces): - mr = MemoryReader(ref_pos, - velocities=ref_vels, - forces=ref_forces) + mr = MemoryReader(ref_pos, velocities=ref_vels, forces=ref_forces) assert mr.ts.has_velocities self.assert_equal_dims(mr.ts.velocities, ref_vels) assert mr.ts.has_forces self.assert_equal_dims(mr.ts.forces, ref_forces) - @pytest.mark.parametrize('param', ['velocities', 'forces']) + @pytest.mark.parametrize("param", ["velocities", "forces"]) def test_wrongshape(self, ref_pos, param): with pytest.raises(ValueError): mr = MemoryReader(ref_pos, **{param: np.zeros((3, 2, 1))}) @@ -328,17 +342,23 @@ class TestMemoryReaderModifications(object): @pytest.fixture() def mr_reader(self): pos = np.arange(self.n_frames * self.n_atoms * 3).reshape( - self.n_frames, self.n_atoms, 3) - vel = np.arange(self.n_frames * self.n_atoms * 3).reshape( - self.n_frames, self.n_atoms, 3) + 200 - frc = np.arange(self.n_frames * self.n_atoms * 3).reshape( - self.n_frames, self.n_atoms, 3) + 400 + self.n_frames, self.n_atoms, 3 + ) + vel = ( + np.arange(self.n_frames * self.n_atoms * 3).reshape( + self.n_frames, self.n_atoms, 3 + ) + + 200 + ) + frc = ( + np.arange(self.n_frames * self.n_atoms * 3).reshape( + self.n_frames, self.n_atoms, 3 + ) + + 400 + ) box = np.arange(self.n_frames * 6).reshape(self.n_frames, 6) + 600 - return MemoryReader(pos, - velocities=vel, - forces=frc, - dimensions=box) + return MemoryReader(pos, velocities=vel, forces=frc, dimensions=box) @pytest.fixture() def mr_universe(self, mr_reader): @@ -347,7 +367,9 @@ def mr_universe(self, mr_reader): return u - @pytest.mark.parametrize('attr', ['positions', 'velocities', 'forces', 'dimensions']) + @pytest.mark.parametrize( + "attr", ["positions", "velocities", "forces", "dimensions"] + ) def test_copying(self, mr_reader, attr): mr2 = mr_reader.copy() # update the attribute @@ -365,7 +387,9 @@ def test_copying(self, mr_reader, attr): # check our old change is still there assert_almost_equal(getattr(ts, attr), 7) - @pytest.mark.parametrize('attr', ['positions', 'velocities', 'forces', 'dimensions']) + @pytest.mark.parametrize( + "attr", ["positions", "velocities", "forces", "dimensions"] + ) def test_attr_set(self, mr_universe, attr): # same as above, but via a Universe/AtomGroup u = mr_universe @@ -384,8 +408,7 @@ def test_attr_set(self, mr_universe, attr): assert u.atoms.forces.shape == (self.n_atoms, 3) assert u.atoms.dimensions.shape == (6,) - @pytest.mark.parametrize('attr', ['velocities', 'forces', 'dimensions']) + @pytest.mark.parametrize("attr", ["velocities", "forces", "dimensions"]) def test_non_numpy_arr(self, attr): with pytest.raises(TypeError): - mr = MemoryReader(np.zeros((10, 30, 3)), - **{attr: 'not an array'}) + mr = MemoryReader(np.zeros((10, 30, 3)), **{attr: "not an array"}) diff --git a/testsuite/MDAnalysisTests/coordinates/test_mmtf.py b/testsuite/MDAnalysisTests/coordinates/test_mmtf.py index a8a3b6037a..8fa7d6a767 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_mmtf.py +++ b/testsuite/MDAnalysisTests/coordinates/test_mmtf.py @@ -32,7 +32,7 @@ class TestMMTFReader(object): - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def r(self): return MMTFReader(MMTF) @@ -40,12 +40,12 @@ def test_read_frame_size(self, r): assert r.ts.n_atoms == 512 def test_read_positions(self, r): - assert_almost_equal(r.ts.positions[0], - np.array([-0.798, 12.632, 23.231]), - decimal=4) - assert_almost_equal(r.ts.positions[-1], - np.array([10.677, 15.517, 11.1]), - decimal=4) + assert_almost_equal( + r.ts.positions[0], np.array([-0.798, 12.632, 23.231]), decimal=4 + ) + assert_almost_equal( + r.ts.positions[-1], np.array([10.677, 15.517, 11.1]), decimal=4 + ) def test_velocities(self, r): assert not r.ts.has_velocities @@ -59,7 +59,7 @@ def test_len(self, r): class TestMMTFReaderGZ(object): - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def r(self): return MMTFReader(MMTF_gz) @@ -67,12 +67,12 @@ def test_read_frame_size(self, r): assert r.ts.n_atoms == 1140 def test_read_positions(self, r): - assert_almost_equal(r.ts.positions[0], - np.array([38.428, 16.440, 28.841]), - decimal=4) - assert_almost_equal(r.ts.positions[-1], - np.array([36.684, 27.024, 20.468]), - decimal=4) + assert_almost_equal( + r.ts.positions[0], np.array([38.428, 16.440, 28.841]), decimal=4 + ) + assert_almost_equal( + r.ts.positions[-1], np.array([36.684, 27.024, 20.468]), decimal=4 + ) def test_velocities(self, r): assert not r.ts.has_velocities @@ -84,6 +84,7 @@ def test_len(self, r): # should be single frame assert len(r) == 1 + def test_dimensionless(): r = MMTFReader(MMTF_skinny2) diff --git a/testsuite/MDAnalysisTests/coordinates/test_mol2.py b/testsuite/MDAnalysisTests/coordinates/test_mol2.py index 450a972eca..494b2ace2a 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_mol2.py +++ b/testsuite/MDAnalysisTests/coordinates/test_mol2.py @@ -24,14 +24,21 @@ import os from numpy.testing import ( - assert_equal, assert_array_equal, - assert_array_almost_equal, TestCase, - assert_almost_equal + assert_equal, + assert_array_equal, + assert_array_almost_equal, + TestCase, + assert_almost_equal, ) from MDAnalysisTests.datafiles import ( - mol2_molecules, mol2_molecule, mol2_broken_molecule, - mol2_zinc, mol2_comments_header, mol2_ligand, mol2_sodium_ion + mol2_molecules, + mol2_molecule, + mol2_broken_molecule, + mol2_zinc, + mol2_comments_header, + mol2_ligand, + mol2_sodium_ion, ) from MDAnalysis import Universe import MDAnalysis as mda @@ -40,7 +47,7 @@ class TestMol2(object): def setup_method(self): - self.outfile = 'test.mol2' + self.outfile = "test.mol2" def test_read(self): u = Universe(mol2_molecules) @@ -48,7 +55,9 @@ 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) @@ -94,9 +103,9 @@ def test_broken_molecule(self): # This doesn't work with 2.6 # Checks the text of the error message, so it low priority - #with self.assertRaises(Exception) as context: + # with self.assertRaises(Exception) as context: # u = Universe(mol2_broken_molecule) - #self.assertEqual("The mol2 block (BrokenMolecule.mol2:0) has no atoms" in context.exception.message, + # self.assertEqual("The mol2 block (BrokenMolecule.mol2:0) has no atoms" in context.exception.message, # True) def test_comments_header(self): @@ -104,7 +113,9 @@ 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 @@ -112,7 +123,7 @@ def test_no_bonds(self, tmpdir): ag = u.atoms assert not hasattr(ag, "bonds") with tmpdir.as_cwd(): - outfile = 'test.mol2' + outfile = "test.mol2" ag.write(outfile) u2 = Universe(outfile) assert not hasattr(u2.atoms, "bonds") @@ -152,17 +163,21 @@ 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(self.universe.trajectory.n_frames, 200, "wrong number of frames in traj") + assert_equal( + self.universe.trajectory.n_frames, + 200, + "wrong number of frames in traj", + ) class TestMOL2NoSubstructure(object): - """MOL2 file without substructure + """MOL2 file without substructure""" - """ n_atoms = 45 def test_load(self): @@ -175,7 +190,7 @@ def test_universe(self): def test_write_nostructure(self, tmpdir): with tmpdir.as_cwd(): - outfile = 'test.mol2' + outfile = "test.mol2" u = mda.Universe(mol2_zinc) with mda.Writer(outfile) as W: @@ -188,23 +203,24 @@ def test_write_nostructure(self, tmpdir): def test_mol2_write_NIE(tmpdir): with tmpdir.as_cwd(): - outfile = os.path.join('test.mol2') + outfile = os.path.join("test.mol2") u = make_Universe(trajectory=True) with pytest.raises(NotImplementedError): u.atoms.write(outfile) + def test_mol2_multi_write(tmpdir): # see: gh-2678 with tmpdir.as_cwd(): u = mda.Universe(mol2_molecules) - u.atoms[:4].write('group1.mol2') - u.atoms[:4].write('group1.mol2') + u.atoms[:4].write("group1.mol2") + u.atoms[:4].write("group1.mol2") def test_mol2_universe_write(tmpdir): # see Issue 2717 with tmpdir.as_cwd(): - outfile = 'test.mol2' + outfile = "test.mol2" u = mda.Universe(mol2_comments_header) diff --git a/testsuite/MDAnalysisTests/coordinates/test_namdbin.py b/testsuite/MDAnalysisTests/coordinates/test_namdbin.py index 9cbce77f2e..cb07b28c1b 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_namdbin.py +++ b/testsuite/MDAnalysisTests/coordinates/test_namdbin.py @@ -24,19 +24,20 @@ import os import pytest -from numpy.testing import (assert_allclose, - assert_equal, - assert_almost_equal) +from numpy.testing import assert_allclose, assert_equal, assert_almost_equal import MDAnalysis as mda from MDAnalysisTests.datafiles import NAMDBIN, PDB_small -from MDAnalysisTests.coordinates.base import (_SingleFrameReader, - BaseReference, - BaseWriterTest) +from MDAnalysisTests.coordinates.base import ( + _SingleFrameReader, + BaseReference, + BaseWriterTest, +) class TestNAMDBINReader(_SingleFrameReader): """Test reading namd binary coordinate file""" + __test__ = True def setUp(self): @@ -52,9 +53,8 @@ def test_parse_n_atoms(self): def test_get_writer_from_reader(self): universe = mda.Universe(PDB_small, NAMDBIN) - writer = universe.trajectory.Writer('NAMDBIN-test') - assert isinstance(writer, - mda.coordinates.NAMDBIN.NAMDBINWriter) + writer = universe.trajectory.Writer("NAMDBIN-test") + assert isinstance(writer, mda.coordinates.NAMDBIN.NAMDBINWriter) class NAMDBINReference(BaseReference): @@ -64,7 +64,7 @@ def __init__(self): self.topology = PDB_small self.reader = mda.coordinates.NAMDBIN.NAMDBINReader self.writer = mda.coordinates.NAMDBIN.NAMDBINWriter - self.ext = 'coor' + self.ext = "coor" self.volume = 0 self.dimensions = np.zeros(6) self.container_format = True @@ -72,6 +72,7 @@ def __init__(self): class NAMDBINWriter(BaseWriterTest): __test__ = True + @staticmethod @pytest.fixture() def ref(): diff --git a/testsuite/MDAnalysisTests/coordinates/test_netcdf.py b/testsuite/MDAnalysisTests/coordinates/test_netcdf.py index dc3456addf..1ebad11665 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_netcdf.py +++ b/testsuite/MDAnalysisTests/coordinates/test_netcdf.py @@ -27,18 +27,23 @@ from scipy.io import netcdf_file import pytest -from numpy.testing import ( - assert_equal, - assert_almost_equal -) +from numpy.testing import assert_equal, assert_almost_equal from MDAnalysis.coordinates.TRJ import NCDFReader, NCDFWriter -from MDAnalysisTests.datafiles import (PFncdf_Top, PFncdf_Trj, - GRO, TRR, XYZ_mini, - PRM_NCBOX, TRJ_NCBOX, DLP_CONFIG, - CPPTRAJ_TRAJ_TOP, CPPTRAJ_TRAJ) +from MDAnalysisTests.datafiles import ( + PFncdf_Top, + PFncdf_Trj, + GRO, + TRR, + XYZ_mini, + PRM_NCBOX, + TRJ_NCBOX, + DLP_CONFIG, + CPPTRAJ_TRAJ_TOP, + CPPTRAJ_TRAJ, +) from MDAnalysisTests.coordinates.test_trj import _TRJReaderTest -from MDAnalysisTests.coordinates.reference import (RefVGV, RefTZ2) +from MDAnalysisTests.coordinates.reference import RefVGV, RefTZ2 from MDAnalysisTests import make_Universe from MDAnalysisTests.util import block_import @@ -52,14 +57,16 @@ def universe(self): def test_slice_iteration(self, universe): frames = [ts.frame for ts in universe.trajectory[4:-2:4]] - assert_equal(frames, - np.arange(universe.trajectory.n_frames)[4:-2:4], - err_msg="slicing did not produce the expected frames") + assert_equal( + frames, + np.arange(universe.trajectory.n_frames)[4:-2:4], + err_msg="slicing did not produce the expected frames", + ) def test_metadata(self, universe): data = universe.trajectory.trjfile - assert_equal(data.Conventions.decode('utf-8'), 'AMBER') - assert_equal(data.ConventionVersion.decode('utf-8'), '1.0') + assert_equal(data.Conventions.decode("utf-8"), "AMBER") + assert_equal(data.ConventionVersion.decode("utf-8"), "1.0") def test_dt(self, universe): ref = 0.0 @@ -67,15 +74,16 @@ def test_dt(self, universe): assert_almost_equal(ref, universe.trajectory.ts.dt, self.prec) def test_get_writer(self, universe): - with universe.trajectory.Writer('out.ncdf') as w: + with universe.trajectory.Writer("out.ncdf") as w: assert w.n_atoms == len(universe.atoms) - assert w.remarks.startswith('AMBER NetCDF format') + 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!' + assert w.remarks == "Hi!" def test_wrong_natoms(self): with pytest.raises(ValueError): @@ -94,6 +102,7 @@ def test_mmap_kwarg(self, universe): # Ugly way to create the tests for mmap + class _NCDFReaderTest_mmap_None(_NCDFReaderTest): @pytest.fixture() def universe(self): @@ -144,46 +153,63 @@ class TestNCDFReader2(object): Contributed by Albert Solernou """ + prec = 3 - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def u(self): return mda.Universe(PFncdf_Top, PFncdf_Trj) def test_positions_1(self, u): """Check positions on first frame""" u.trajectory[0] - ref_1 = np.array([[-0.11980818, 18.70524979, 11.6477766 - ], [-0.44717646, 18.61727142, 12.59919548], - [-0.60952115, 19.47885513, 11.22137547]], - dtype=np.float32) + ref_1 = np.array( + [ + [-0.11980818, 18.70524979, 11.6477766], + [-0.44717646, 18.61727142, 12.59919548], + [-0.60952115, 19.47885513, 11.22137547], + ], + dtype=np.float32, + ) assert_almost_equal(ref_1, u.atoms.positions[:3], self.prec) def test_positions_2(self, u): """Check positions on second frame""" u.trajectory[1] - ref_2 = np.array([[-0.13042036, 18.6671524, 11.69647026 - ], [-0.46643803, 18.60186768, 12.646698], - [-0.46567637, 19.49173927, 11.21922874]], - dtype=np.float32) + ref_2 = np.array( + [ + [-0.13042036, 18.6671524, 11.69647026], + [-0.46643803, 18.60186768, 12.646698], + [-0.46567637, 19.49173927, 11.21922874], + ], + dtype=np.float32, + ) assert_almost_equal(ref_2, u.atoms.positions[:3], self.prec) def test_forces_1(self, u): """Check forces on first frame""" u.trajectory[0] - ref_1 = np.array([[49.23017883, -97.05565643, -86.09863281 - ], [2.97547197, 29.84169388, 11.12069607], - [-15.93093777, 14.43616867, 30.25889015]], - dtype=np.float32) + ref_1 = np.array( + [ + [49.23017883, -97.05565643, -86.09863281], + [2.97547197, 29.84169388, 11.12069607], + [-15.93093777, 14.43616867, 30.25889015], + ], + dtype=np.float32, + ) assert_almost_equal(ref_1, u.atoms.forces[:3], self.prec) def test_forces_2(self, u): """Check forces on second frame""" u.trajectory[1] - ref_2 = np.array([[116.39096832, -145.44448853, -151.3155365 - ], [-18.90058327, 27.20145798, 1.95245135], - [-31.08556366, 14.95863628, 41.10367966]], - dtype=np.float32) + ref_2 = np.array( + [ + [116.39096832, -145.44448853, -151.3155365], + [-18.90058327, 27.20145798, 1.95245135], + [-31.08556366, 14.95863628, 41.10367966], + ], + dtype=np.float32, + ) assert_almost_equal(ref_2, u.atoms.forces[:3], self.prec) def test_time_1(self, u): @@ -211,80 +237,113 @@ class TestNCDFReader3(object): Added to address Issue #2323 """ + prec = 3 # Expected coordinates as stored in Angstrom units - coord_refs = np.array([ - [[15.249873, 12.578178, 15.191731], - [14.925511, 13.58888, 14.944009], - [15.285703, 14.3409605, 15.645962]], - [[14.799454, 15.214347, 14.714555], - [15.001984, 15.870884, 13.868363], - [16.03358, 16.183628, 14.02995]] - ], dtype=np.float32) + coord_refs = np.array( + [ + [ + [15.249873, 12.578178, 15.191731], + [14.925511, 13.58888, 14.944009], + [15.285703, 14.3409605, 15.645962], + ], + [ + [14.799454, 15.214347, 14.714555], + [15.001984, 15.870884, 13.868363], + [16.03358, 16.183628, 14.02995], + ], + ], + dtype=np.float32, + ) # Expected forces as stored in kcal/(mol*Angstrom) - frc_refs = np.array([ - [[8.583388, 1.8023694, -15.0033455], - [-21.594835, 39.09166, 6.567963], - [4.363016, -12.135163, 4.4775457]], - [[-10.106646, -7.870829, -10.385734], - [7.23599, -12.366022, -9.106191], - [-4.637955, 11.597565, -6.463743]] - ], dtype=np.float32) + frc_refs = np.array( + [ + [ + [8.583388, 1.8023694, -15.0033455], + [-21.594835, 39.09166, 6.567963], + [4.363016, -12.135163, 4.4775457], + ], + [ + [-10.106646, -7.870829, -10.385734], + [7.23599, -12.366022, -9.106191], + [-4.637955, 11.597565, -6.463743], + ], + ], + dtype=np.float32, + ) # Expected velocities as stored in Angstrom per AKMA time unit # These are usually associated with a scale_factor of 20.455 - vel_refs = np.array([ - [[-0.5301689, -0.16311595, -0.31390688], - [0.00188578, 0.02513031, -0.2687525], - [0.84072256, 0.09402391, -0.7457009]], - [[-1.7773226, 1.2307, 0.50276583], - [-0.13532305, 0.1355039, -0.05567304], - [-0.6182481, 1.6396415, 0.46686798]] - ], dtype=np.float32) + vel_refs = np.array( + [ + [ + [-0.5301689, -0.16311595, -0.31390688], + [0.00188578, 0.02513031, -0.2687525], + [0.84072256, 0.09402391, -0.7457009], + ], + [ + [-1.7773226, 1.2307, 0.50276583], + [-0.13532305, 0.1355039, -0.05567304], + [-0.6182481, 1.6396415, 0.46686798], + ], + ], + dtype=np.float32, + ) # Expected box values as stored in cell_lengths ([:3]) of Angstrom # and cell_angles ([:3]) of degree - box_refs = np.array([ - [28.81876287, 28.27875261, 27.72616397, 90., 90., 90.], - [27.06266081, 26.55555665, 26.03664058, 90., 90., 90.] - ], dtype=np.float32) - - @pytest.fixture(scope='class') + box_refs = np.array( + [ + [28.81876287, 28.27875261, 27.72616397, 90.0, 90.0, 90.0], + [27.06266081, 26.55555665, 26.03664058, 90.0, 90.0, 90.0], + ], + dtype=np.float32, + ) + + @pytest.fixture(scope="class") def universe(self): return mda.Universe(PRM_NCBOX, TRJ_NCBOX) - @pytest.mark.parametrize('index,expected', ((0, 0), (8, 1))) + @pytest.mark.parametrize("index,expected", ((0, 0), (8, 1))) def test_positions(self, universe, index, expected): universe.trajectory[index] - assert_almost_equal(self.coord_refs[expected], - universe.atoms.positions[:3], self.prec) + assert_almost_equal( + self.coord_refs[expected], universe.atoms.positions[:3], self.prec + ) - @pytest.mark.parametrize('index,expected', ((0, 0), (8, 1))) + @pytest.mark.parametrize("index,expected", ((0, 0), (8, 1))) def test_forces(self, universe, index, expected): """Here we multiply the forces by 4.184 to convert from kcal to kj in order to verify that MDA has correctly read and converted the units from those stored in the NetCDF file. """ universe.trajectory[index] - assert_almost_equal(self.frc_refs[expected] * 4.184, - universe.atoms.forces[:3], self.prec) + assert_almost_equal( + self.frc_refs[expected] * 4.184, + universe.atoms.forces[:3], + self.prec, + ) - @pytest.mark.parametrize('index,expected', ((0, 0), (8, 1))) + @pytest.mark.parametrize("index,expected", ((0, 0), (8, 1))) def test_velocities(self, universe, index, expected): """Here we multiply the velocities by 20.455 to match the value of `scale_factor` which has been declared in the NetCDF file, which should change the values from Angstrom/AKMA time unit to Angstrom/ps. """ universe.trajectory[index] - assert_almost_equal(self.vel_refs[expected] * 20.455, - universe.atoms.velocities[:3], self.prec) + assert_almost_equal( + self.vel_refs[expected] * 20.455, + universe.atoms.velocities[:3], + self.prec, + ) - @pytest.mark.parametrize('index,expected', ((0, 1.0), (8, 9.0))) + @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) @@ -294,7 +353,7 @@ def test_dt(self, universe): assert_almost_equal(ref, universe.trajectory.dt, self.prec) assert_almost_equal(ref, universe.trajectory.ts.dt, self.prec) - @pytest.mark.parametrize('index,expected', ((0, 0), (8, 1))) + @pytest.mark.parametrize("index,expected", ((0, 0), (8, 1))) def test_box(self, universe, index, expected): universe.trajectory[index] assert_almost_equal(self.box_refs[expected], universe.dimensions) @@ -302,12 +361,12 @@ def test_box(self, universe, index, expected): class TestNCDFReader4(object): """NCDF Trajectory exported by cpptaj, without `time` variable.""" + prec = 3 - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def u(self): - return mda.Universe(CPPTRAJ_TRAJ_TOP, - [CPPTRAJ_TRAJ, CPPTRAJ_TRAJ]) + return mda.Universe(CPPTRAJ_TRAJ_TOP, [CPPTRAJ_TRAJ, CPPTRAJ_TRAJ]) def test_chain_times(self, u): """Check times entries for a chain of trajectories without @@ -322,8 +381,10 @@ def test_dt(self, u): assert u.trajectory.ts.dt == pytest.approx(ref) def test_warn_user_no_time_information(self, u): - 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" + ) with pytest.warns(UserWarning, match=wmsg): u2 = mda.Universe(CPPTRAJ_TRAJ_TOP, CPPTRAJ_TRAJ) @@ -335,116 +396,139 @@ class _NCDFGenerator(object): def create_ncdf(self, params): """A basic modular ncdf writer based on :class:`NCDFWriter`""" # Create under context manager - with netcdf_file(params['filename'], mode='w', - version=params['version_byte']) as ncdf: + with netcdf_file( + params["filename"], mode="w", version=params["version_byte"] + ) as ncdf: # Top level attributes - if params['Conventions']: - setattr(ncdf, 'Conventions', params['Conventions']) - if params['ConventionVersion']: - setattr(ncdf, 'ConventionVersion', - params['ConventionVersion']) - if params['program']: - setattr(ncdf, 'program', params['program']) - if params['programVersion']: - setattr(ncdf, 'programVersion', params['programVersion']) + if params["Conventions"]: + setattr(ncdf, "Conventions", params["Conventions"]) + if params["ConventionVersion"]: + setattr(ncdf, "ConventionVersion", params["ConventionVersion"]) + if params["program"]: + setattr(ncdf, "program", params["program"]) + if params["programVersion"]: + setattr(ncdf, "programVersion", params["programVersion"]) # Dimensions - if params['frame']: - ncdf.createDimension('frame', None) - if params['n_atoms']: - ncdf.createDimension('atom', params['n_atoms']) - if params['spatial']: - ncdf.createDimension('spatial', params['spatial']) - if params['time']: - ncdf.createDimension('time', 1) - ncdf.createDimension('label', 5) - ncdf.createDimension('cell_spatial', 3) - ncdf.createDimension('cell_angular', 3) + if params["frame"]: + ncdf.createDimension("frame", None) + if params["n_atoms"]: + ncdf.createDimension("atom", params["n_atoms"]) + if params["spatial"]: + ncdf.createDimension("spatial", params["spatial"]) + if params["time"]: + ncdf.createDimension("time", 1) + ncdf.createDimension("label", 5) + ncdf.createDimension("cell_spatial", 3) + ncdf.createDimension("cell_angular", 3) # Variables - if params['time']: - time = ncdf.createVariable('time', 'd', ('time',)) - setattr(time, 'units', params['time']) + if params["time"]: + 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[:] = 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_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")] + ) # Spatial or atom dependent variables - if (params['spatial']) and (params['n_atoms']): - spatial = ncdf.createVariable('spatial', 'c', ('spatial',)) - spatial[:] = np.asarray(list('xyz')[:params['spatial']]) - if params['frame']: - if params['coordinates']: - coords = ncdf.createVariable('coordinates', 'f4', - ('frame', 'atom', - 'spatial')) - velocs = ncdf.createVariable('velocities', 'f4', - ('frame', 'atom', 'spatial')) - forces = ncdf.createVariable('forces', 'f4', - ('frame', 'atom', 'spatial')) - cell_lengths = ncdf.createVariable('cell_lengths', 'f8', - ('frame', - 'cell_spatial')) - cell_angles = ncdf.createVariable('cell_angles', 'f8', - ('frame', - 'cell_angular')) + if (params["spatial"]) and (params["n_atoms"]): + spatial = ncdf.createVariable("spatial", "c", ("spatial",)) + spatial[:] = np.asarray(list("xyz")[: params["spatial"]]) + if params["frame"]: + if params["coordinates"]: + coords = ncdf.createVariable( + "coordinates", "f4", ("frame", "atom", "spatial") + ) + velocs = ncdf.createVariable( + "velocities", "f4", ("frame", "atom", "spatial") + ) + forces = ncdf.createVariable( + "forces", "f4", ("frame", "atom", "spatial") + ) + cell_lengths = ncdf.createVariable( + "cell_lengths", "f8", ("frame", "cell_spatial") + ) + cell_angles = ncdf.createVariable( + "cell_angles", "f8", ("frame", "cell_angular") + ) else: - if params['coordinates']: - coords = ncdf.createVariable('coordinates', 'f8', - ('atom', 'spatial')) - cell_lengths = ncdf.createVariable('cell_lengths', 'f8', - ('cell_spatial',)) - cell_angles = ncdf.createVariable('cell_angles', 'f8', - ('cell_angular',)) - velocs = ncdf.createVariable('velocities', 'f8', - ('atom', 'spatial')) - forces = ncdf.createVariable('forces', 'f8', - ('atom', 'spatial')) + if params["coordinates"]: + coords = ncdf.createVariable( + "coordinates", "f8", ("atom", "spatial") + ) + cell_lengths = ncdf.createVariable( + "cell_lengths", "f8", ("cell_spatial",) + ) + cell_angles = ncdf.createVariable( + "cell_angles", "f8", ("cell_angular",) + ) + velocs = ncdf.createVariable( + "velocities", "f8", ("atom", "spatial") + ) + forces = ncdf.createVariable( + "forces", "f8", ("atom", "spatial") + ) # Set units - if params['coordinates']: - setattr(coords, 'units', params['coordinates']) - setattr(velocs, 'units', params['velocities']) - setattr(forces, 'units', params['forces']) - setattr(cell_lengths, 'units', params['cell_lengths']) - setattr(cell_angles, 'units', params['cell_angles']) + if params["coordinates"]: + setattr(coords, "units", params["coordinates"]) + setattr(velocs, "units", params["velocities"]) + setattr(forces, "units", params["forces"]) + setattr(cell_lengths, "units", params["cell_lengths"]) + setattr(cell_angles, "units", params["cell_angles"]) # Assign value - if params['frame']: - for index in range(params['frame']): - if params['coordinates']: + if params["frame"]: + for index in range(params["frame"]): + if params["coordinates"]: coords[index, :] = np.asarray( - range(params['spatial']), dtype=np.float32) - cell_lengths[index, :] = np.array([20., 20., 20.], - dtype=np.float32) - cell_angles[index, :] = np.array([90., 90., 90.], - dtype=np.float32) - velocs[index, :] = np.asarray(range(params['spatial']), - dtype=np.float32) - forces[index, :] = np.asarray(range(params['spatial']), - dtype=np.float32) + range(params["spatial"]), dtype=np.float32 + ) + cell_lengths[index, :] = np.array( + [20.0, 20.0, 20.0], dtype=np.float32 + ) + cell_angles[index, :] = np.array( + [90.0, 90.0, 90.0], dtype=np.float32 + ) + velocs[index, :] = np.asarray( + range(params["spatial"]), dtype=np.float32 + ) + forces[index, :] = np.asarray( + range(params["spatial"]), dtype=np.float32 + ) else: - if params['coordinates']: - coords[:] = np.asarray(range(params['spatial']), - dtype=np.float32) - cell_lengths[:] = np.array([20., 20., 20.], - dtype=np.float32) - cell_angles[:] = np.array([90., 90., 90.], - dtype=np.float32) - velocs[:] = np.asarray(range(params['spatial']), - dtype=np.float32) - forces[:] = np.asarray(range(params['spatial']), - dtype=np.float32) + if params["coordinates"]: + 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 + ) # self.scale_factor overrides which variable gets a scale_factor - if params['scale_factor']: - setattr(ncdf.variables[params['scale_factor']], - 'scale_factor', params['scale_factor_value']) + if params["scale_factor"]: + setattr( + ncdf.variables[params["scale_factor"]], + "scale_factor", + params["scale_factor_value"], + ) def gen_params(self, keypair=None, restart=False): """Generate writer parameters, keypair can be used to overwrite @@ -452,28 +536,28 @@ def gen_params(self, keypair=None, restart=False): """ params = { - 'filename': 'test.nc', - 'version_byte': 2, - 'Conventions': 'AMBER', - 'ConventionVersion': '1.0', - 'program': 'mda test_writer', - 'programVersion': 'V42', - 'n_atoms': 1, - 'spatial': 3, - 'coordinates': 'angstrom', - 'velocities': 'angstrom/picosecond', - 'forces': 'kilocalorie/mole/angstrom', - 'cell_lengths': 'angstrom', - 'cell_angles': 'degree', - 'time': 'picosecond', - 'scale_factor': None, - 'scale_factor_value': 2.0, - 'frame': 2 + "filename": "test.nc", + "version_byte": 2, + "Conventions": "AMBER", + "ConventionVersion": "1.0", + "program": "mda test_writer", + "programVersion": "V42", + "n_atoms": 1, + "spatial": 3, + "coordinates": "angstrom", + "velocities": "angstrom/picosecond", + "forces": "kilocalorie/mole/angstrom", + "cell_lengths": "angstrom", + "cell_angles": "degree", + "time": "picosecond", + "scale_factor": None, + "scale_factor_value": 2.0, + "frame": 2, } if restart: - params['filename'] = 'test.ncrst' - params['frame'] = None + params["filename"] = "test.ncrst" + params["frame"] = None if keypair: for entry in keypair: @@ -487,150 +571,166 @@ class TestScaleFactorImplementation(_NCDFGenerator): prec = 5 def test_scale_factor_coordinates(self, tmpdir): - mutation = {'scale_factor': 'coordinates'} + mutation = {"scale_factor": "coordinates"} params = self.gen_params(keypair=mutation, restart=False) expected = np.asarray(range(3), dtype=np.float32) * 2.0 with tmpdir.as_cwd(): self.create_ncdf(params) - u = mda.Universe(params['filename'], to_guess=()) + u = mda.Universe(params["filename"], to_guess=()) for ts in u.trajectory: assert_almost_equal(ts.positions[0], expected, self.prec) def test_scale_factor_velocities(self, tmpdir): - mutation = {'scale_factor': 'velocities', 'scale_factor_value': 3.0} + mutation = {"scale_factor": "velocities", "scale_factor_value": 3.0} params = self.gen_params(keypair=mutation, restart=False) expected = np.asarray(range(3), dtype=np.float32) * 3.0 with tmpdir.as_cwd(): self.create_ncdf(params) - u = mda.Universe(params['filename'], to_guess=()) + u = mda.Universe(params["filename"], to_guess=()) for ts in u.trajectory: assert_almost_equal(ts.velocities[0], expected, self.prec) def test_scale_factor_forces(self, tmpdir): - mutation = {'scale_factor': 'forces', 'scale_factor_value': 10.0} + mutation = {"scale_factor": "forces", "scale_factor_value": 10.0} params = self.gen_params(keypair=mutation, restart=False) expected = np.asarray(range(3), dtype=np.float32) * 10.0 * 4.184 with tmpdir.as_cwd(): self.create_ncdf(params) - u = mda.Universe(params['filename'], to_guess=()) + u = mda.Universe(params["filename"], to_guess=()) for ts in u.trajectory: assert_almost_equal(ts.forces[0], expected, self.prec) - @pytest.mark.parametrize('mutation,expected', ( - ({'scale_factor': 'cell_lengths', 'scale_factor_value': 0.75}, - np.array([15., 15., 15., 90., 90., 90.])), - ({'scale_factor': 'cell_angles', 'scale_factor_value': 0.5}, - np.array([20., 20., 20., 45., 45., 45.])) - )) + @pytest.mark.parametrize( + "mutation,expected", + ( + ( + {"scale_factor": "cell_lengths", "scale_factor_value": 0.75}, + np.array([15.0, 15.0, 15.0, 90.0, 90.0, 90.0]), + ), + ( + {"scale_factor": "cell_angles", "scale_factor_value": 0.5}, + np.array([20.0, 20.0, 20.0, 45.0, 45.0, 45.0]), + ), + ), + ) def test_scale_factor_box(self, tmpdir, mutation, expected): params = self.gen_params(keypair=mutation, restart=False) with tmpdir.as_cwd(): self.create_ncdf(params) - u = mda.Universe(params['filename'], to_guess=()) + u = mda.Universe(params["filename"], to_guess=()) for ts in u.trajectory: assert_almost_equal(ts.dimensions, expected, self.prec) def test_scale_factor_not_float(self, tmpdir): - mutation = {'scale_factor': 'coordinates', - 'scale_factor_value': 'parsnips'} + mutation = { + "scale_factor": "coordinates", + "scale_factor_value": "parsnips", + } params = self.gen_params(keypair=mutation, restart=False) with tmpdir.as_cwd(): self.create_ncdf(params) errmsg = "b'parsnips' is not a float" with pytest.raises(TypeError, match=errmsg): - u = mda.Universe(params['filename']) + u = mda.Universe(params["filename"]) class TestNCDFReaderExceptionsWarnings(_NCDFGenerator): - @pytest.mark.parametrize('mutation', [ - {'Conventions': 'Foo'}, - {'version_byte': 1}, - {'spatial': 2} - ]) + @pytest.mark.parametrize( + "mutation", + [{"Conventions": "Foo"}, {"version_byte": 1}, {"spatial": 2}], + ) def test_type_errors(self, tmpdir, mutation): params = self.gen_params(keypair=mutation, restart=False) with tmpdir.as_cwd(): self.create_ncdf(params) with pytest.raises(TypeError): - NCDFReader(params['filename']) - - @pytest.mark.parametrize('mutation', [ - {'Conventions': None}, - {'ConventionVersion': None}, - {'spatial': None}, - {'n_atoms': None}, - {'frame': None} - ]) + NCDFReader(params["filename"]) + + @pytest.mark.parametrize( + "mutation", + [ + {"Conventions": None}, + {"ConventionVersion": None}, + {"spatial": None}, + {"n_atoms": None}, + {"frame": None}, + ], + ) def test_value_errors(self, tmpdir, mutation): params = self.gen_params(keypair=mutation, restart=False) with tmpdir.as_cwd(): self.create_ncdf(params) with pytest.raises(ValueError): - NCDFReader(params['filename']) - - @pytest.mark.parametrize('mutation', [ - {'scale_factor': 'cell_spatial'}, - {'time': 'femtosecond'}, - {'coordinates': 'nanometer'}, - {'velocities': 'angstrom/akma'}, - {'forces': 'kilojoule/mole/angstrom'}, - {'cell_lengths': 'nanometer'}, - {'cell_angles': 'radians'} - ]) + NCDFReader(params["filename"]) + + @pytest.mark.parametrize( + "mutation", + [ + {"scale_factor": "cell_spatial"}, + {"time": "femtosecond"}, + {"coordinates": "nanometer"}, + {"velocities": "angstrom/akma"}, + {"forces": "kilojoule/mole/angstrom"}, + {"cell_lengths": "nanometer"}, + {"cell_angles": "radians"}, + ], + ) def test_notimplemented_errors(self, tmpdir, mutation): params = self.gen_params(keypair=mutation, restart=False) with tmpdir.as_cwd(): self.create_ncdf(params) with pytest.raises(NotImplementedError): - NCDFReader(params['filename']) + NCDFReader(params["filename"]) - @pytest.mark.parametrize('evaluate,expected', ( - ('yard', 'foot'), - ('second', 'minute') - )) + @pytest.mark.parametrize( + "evaluate,expected", (("yard", "foot"), ("second", "minute")) + ) def test_verify_units_errors(self, evaluate, expected): """Directly tests expected failures of _verify_units""" with pytest.raises(NotImplementedError): - NCDFReader._verify_units(evaluate.encode('utf-8'), expected) + NCDFReader._verify_units(evaluate.encode("utf-8"), expected) def test_ioerror(self, tmpdir): params = self.gen_params(restart=False) with tmpdir.as_cwd(): self.create_ncdf(params) with pytest.raises(IOError): - u = mda.Universe(params['filename'], to_guess=()) + u = mda.Universe(params["filename"], to_guess=()) u.trajectory.close() u.trajectory[-1] def test_conventionversion_warn(self, tmpdir): - mutation = {'ConventionVersion': '2.0'} + mutation = {"ConventionVersion": "2.0"} params = self.gen_params(keypair=mutation, restart=False) with tmpdir.as_cwd(): self.create_ncdf(params) with pytest.warns(UserWarning) as record: - NCDFReader(params['filename']) + NCDFReader(params["filename"]) assert len(record) == 1 - wmsg = ("NCDF trajectory format is 2.0 but the reader " - "implements format 1.0") + wmsg = ( + "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(): self.create_ncdf(params) with pytest.warns(UserWarning) as record: - NCDFReader(params['filename']) + NCDFReader(params["filename"]) assert len(record) == 1 - wmsg = ("NCDF trajectory test.nc may not fully adhere to AMBER " - "standards as either the `program` or `programVersion` " - "attributes are missing") + wmsg = ( + "NCDF trajectory test.nc may not fully adhere to AMBER " + "standards as either the `program` or `programVersion` " + "attributes are missing" + ) assert str(record[0].message.args[0]) == wmsg def test_no_dt_warning(self, tmpdir): @@ -638,13 +738,13 @@ def test_no_dt_warning(self, tmpdir): Also at the same time checks that single frame chain reading works""" u = mda.Universe(PFncdf_Top, PFncdf_Trj) with tmpdir.as_cwd(): - with NCDFWriter('single_frame.nc', u.atoms.n_atoms) as W: + with NCDFWriter("single_frame.nc", u.atoms.n_atoms) as W: W.write(u) # Using the ChainReader implicitly calls dt() and thus _get_dt() wmsg = "Reader has no dt information, set to 1.0 ps" with pytest.warns(UserWarning, match=wmsg): - u2 = mda.Universe(PFncdf_Top, [PFncdf_Trj, 'single_frame.nc']) + u2 = mda.Universe(PFncdf_Top, [PFncdf_Trj, "single_frame.nc"]) class _NCDFWriterTest(object): @@ -654,19 +754,19 @@ class _NCDFWriterTest(object): def universe(self): return mda.Universe(self.topology, self.filename) - @pytest.fixture(params=['nc', 'ncdf']) + @pytest.fixture(params=["nc", "ncdf"]) def outfile_extensions(self, tmpdir, request): # Issue 3030, test all extensions of NCDFWriter ext = request.param - return str(tmpdir) + f'ncdf-writer-1.{ext}' + return str(tmpdir) + f"ncdf-writer-1.{ext}" @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir) + 'ncdf-writer-1.ncdf' + return str(tmpdir) + "ncdf-writer-1.ncdf" @pytest.fixture() def outtop(self, tmpdir): - return str(tmpdir) + 'ncdf-writer-top.pdb' + return str(tmpdir) + "ncdf-writer-top.pdb" def _test_write_trajectory(self, universe, outfile): # explicit import so that we can artifically remove netCDF4 @@ -685,15 +785,21 @@ def _test_write_trajectory(self, universe, outfile): # which should be "float32". # See http://docs.scipy.org/doc/numpy-1.10.0/reference/arrays.dtypes.html # and https://github.com/MDAnalysis/mdanalysis/pull/503 - dataset = netcdf_file(outfile, 'r') - coords = dataset.variables['coordinates'] - time = dataset.variables['time'] - assert_equal(coords[:].dtype.name, np.dtype(np.float32).name, - 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)) + dataset = netcdf_file(outfile, "r") + coords = dataset.variables["coordinates"] + time = dataset.variables["time"] + assert_equal( + coords[:].dtype.name, + np.dtype(np.float32).name, + 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), + ) def test_write_trajectory_netCDF4(self, universe, outfile): pytest.importorskip("netCDF4") @@ -701,16 +807,19 @@ def test_write_trajectory_netCDF4(self, universe, outfile): def test_write_trajectory_netcdf(self, universe, outfile): import MDAnalysis.coordinates.TRJ - loaded_netCDF4 = sys.modules['MDAnalysis.coordinates.TRJ'].netCDF4 + + loaded_netCDF4 = sys.modules["MDAnalysis.coordinates.TRJ"].netCDF4 try: # cannot use @block_import('netCDF4') because TRJ was already imported # during setup() and already sits in the global module list so we just # set it to None because that is what TRJ does if it cannot find netCDF4 - sys.modules['MDAnalysis.coordinates.TRJ'].netCDF4 = None - assert MDAnalysis.coordinates.TRJ.netCDF4 is None # should happen if netCDF4 not found + sys.modules["MDAnalysis.coordinates.TRJ"].netCDF4 = None + assert ( + MDAnalysis.coordinates.TRJ.netCDF4 is None + ) # should happen if netCDF4 not found return self._test_write_trajectory(universe, outfile) finally: - sys.modules['MDAnalysis.coordinates.TRJ'].netCDF4 = loaded_netCDF4 + sys.modules["MDAnalysis.coordinates.TRJ"].netCDF4 = loaded_netCDF4 def test_OtherWriter(self, universe, outfile_extensions): t = universe.trajectory @@ -726,22 +835,30 @@ def _check_new_traj(self, universe, outfile): uw = mda.Universe(self.topology, outfile) # check that the trajectories are identical for each time step - for orig_ts, written_ts in zip(universe.trajectory, - uw.trajectory): - assert_almost_equal(written_ts._pos, orig_ts._pos, self.prec, - err_msg="coordinate mismatch between " - "original and written trajectory at " - "frame %d (orig) vs %d (written)" % ( - orig_ts.frame, - written_ts.frame)) + for orig_ts, written_ts in zip(universe.trajectory, uw.trajectory): + assert_almost_equal( + written_ts._pos, + orig_ts._pos, + self.prec, + err_msg="coordinate mismatch between " + "original and written trajectory at " + "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)) - assert_almost_equal(written_ts.dimensions, - orig_ts.dimensions, - self.prec, - err_msg="unitcells are not identical") + 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), + ) + assert_almost_equal( + written_ts.dimensions, + orig_ts.dimensions, + self.prec, + err_msg="unitcells are not identical", + ) # check that the NCDF data structures are the same nc_orig = universe.trajectory.trjfile nc_copy = uw.trajectory.trjfile @@ -752,58 +869,84 @@ def _check_new_traj(self, universe, outfile): try: dim_new = nc_copy.dimensions[k] except KeyError: - raise AssertionError("NCDFWriter did not write " - "dimension '{0}'".format(k)) + raise AssertionError( + "NCDFWriter did not write " "dimension '{0}'".format(k) + ) else: - assert_equal(dim, dim_new, - err_msg="Dimension '{0}' size mismatch".format(k)) + assert_equal( + dim, + dim_new, + err_msg="Dimension '{0}' size mismatch".format(k), + ) for k, v in nc_orig.variables.items(): try: v_new = nc_copy.variables[k] except KeyError: - raise AssertionError("NCDFWriter did not write " - "variable '{0}'".format(k)) + raise AssertionError( + "NCDFWriter did not write " "variable '{0}'".format(k) + ) else: try: - assert_almost_equal(v[:], v_new[:], self.prec, - err_msg="Variable '{0}' not " - "written correctly".format( - k)) + assert_almost_equal( + v[:], + v_new[:], + self.prec, + 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)) + assert_equal( + v[:], + v_new[:], + err_msg="Variable {0} not written " + "correctly".format(k), + ) def test_TRR2NCDF(self, outfile): trr = mda.Universe(GRO, TRR) - with mda.Writer(outfile, trr.trajectory.n_atoms, - velocities=True, format="ncdf") as W: + with mda.Writer( + outfile, trr.trajectory.n_atoms, velocities=True, format="ncdf" + ) as W: for ts in trr.trajectory: W.write(trr) uw = mda.Universe(GRO, outfile) - for orig_ts, written_ts in zip(trr.trajectory, - uw.trajectory): - assert_almost_equal(written_ts._pos, orig_ts._pos, self.prec, - err_msg="coordinate mismatch between " - "original and written trajectory at " - "frame {0} (orig) vs {1} (written)".format( - orig_ts.frame, written_ts.frame)) - assert_almost_equal(written_ts._velocities, - orig_ts._velocities, self.prec, - err_msg="velocity mismatch between " - "original and written trajectory at " - "frame {0} (orig) vs {1} (written)".format( - 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)) - assert_almost_equal(written_ts.dimensions, - orig_ts.dimensions, - self.prec, - err_msg="unitcells are not identical") + for orig_ts, written_ts in zip(trr.trajectory, uw.trajectory): + assert_almost_equal( + written_ts._pos, + orig_ts._pos, + self.prec, + err_msg="coordinate mismatch between " + "original and written trajectory at " + "frame {0} (orig) vs {1} (written)".format( + orig_ts.frame, written_ts.frame + ), + ) + assert_almost_equal( + written_ts._velocities, + orig_ts._velocities, + self.prec, + err_msg="velocity mismatch between " + "original and written trajectory at " + "frame {0} (orig) vs {1} (written)".format( + 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), + ) + assert_almost_equal( + written_ts.dimensions, + orig_ts.dimensions, + self.prec, + err_msg="unitcells are not identical", + ) del trr def test_write_AtomGroup(self, universe, outfile, outtop): @@ -817,21 +960,29 @@ def test_write_AtomGroup(self, universe, outfile, outtop): uw = mda.Universe(outtop, outfile) pw = uw.atoms - for orig_ts, written_ts in zip(universe.trajectory, - uw.trajectory): - assert_almost_equal(p.positions, pw.positions, self.prec, - err_msg="coordinate mismatch between " - "original and written trajectory at " - "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)) - assert_almost_equal(written_ts.dimensions, - orig_ts.dimensions, - self.prec, - err_msg="unitcells are not identical") + for orig_ts, written_ts in zip(universe.trajectory, uw.trajectory): + assert_almost_equal( + p.positions, + pw.positions, + self.prec, + err_msg="coordinate mismatch between " + "original and written trajectory at " + "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), + ) + assert_almost_equal( + written_ts.dimensions, + orig_ts.dimensions, + self.prec, + err_msg="unitcells are not identical", + ) class TestNCDFWriter(_NCDFWriterTest, RefVGV): @@ -844,14 +995,19 @@ class TestNCDFWriterTZ2(_NCDFWriterTest, RefTZ2): class TestNCDFWriterVelsForces(object): """Test writing NCDF trajectories with a mixture of options""" + prec = 3 top = XYZ_mini n_atoms = 3 @pytest.fixture() def u1(self): - u = make_Universe(size=(self.n_atoms, 1, 1), trajectory=True, - velocities=True, forces=True) + u = make_Universe( + size=(self.n_atoms, 1, 1), + trajectory=True, + velocities=True, + forces=True, + ) # Memory reader so changes should be in-place u.atoms.velocities += 100 u.atoms.forces += 200 @@ -859,31 +1015,37 @@ def u1(self): @pytest.fixture() def u2(self): - u = make_Universe(size=(self.n_atoms, 1, 1), trajectory=True, - velocities=True, forces=True) + u = make_Universe( + size=(self.n_atoms, 1, 1), + trajectory=True, + velocities=True, + forces=True, + ) # Memory reader so changes should be in-place u.atoms.positions += 300 u.atoms.velocities += 400 u.atoms.forces += 500 return u - @pytest.mark.parametrize('pos, vel, force', ( + @pytest.mark.parametrize( + "pos, vel, force", + ( (True, False, False), (True, True, False), (True, False, True), (True, True, True), - )) + ), + ) def test_write_u(self, pos, vel, force, tmpdir, u1, u2): """Write the two reference universes, then open them up and check values pos vel and force are bools which define whether these properties should be in universe """ - outfile = str(tmpdir) + 'ncdf-write-vels-force.ncdf' - with NCDFWriter(outfile, - n_atoms=self.n_atoms, - velocities=vel, - forces=force) as w: + outfile = str(tmpdir) + "ncdf-write-vels-force.ncdf" + with NCDFWriter( + outfile, n_atoms=self.n_atoms, velocities=vel, forces=force + ) as w: w.write(u1) w.write(u2) @@ -895,23 +1057,26 @@ 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') + 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') + getattr(ts, "velocities") if force: assert_almost_equal(ts._forces, ref_ts._forces, self.prec) else: with pytest.raises(mda.NoDataError): - getattr(ts, 'forces') + getattr(ts, "forces") u.trajectory.close() @@ -922,11 +1087,11 @@ class TestNCDFWriterScaleFactors: @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir) + 'ncdf-write-scale.ncdf' + return str(tmpdir) + "ncdf-write-scale.ncdf" @pytest.fixture() def outfile2(self, tmpdir): - return str(tmpdir) + 'ncdf-write-scale2.ncdf' + return str(tmpdir) + "ncdf-write-scale2.ncdf" @pytest.fixture() def universe(self): @@ -939,7 +1104,7 @@ def get_scale_factors(self, ncdfile): # be faster & ok to set it to True with netcdf_file(ncdfile, mmap=False) as f: for var in f.variables: - if hasattr(f.variables[var], 'scale_factor'): + if hasattr(f.variables[var], "scale_factor"): sfactors[var] = f.variables[var].scale_factor return sfactors @@ -956,30 +1121,53 @@ def test_write_read_factors_default(self, outfile, universe): # check scale_factors sfactors = self.get_scale_factors(outfile) assert len(sfactors) == 1 - assert sfactors['velocities'] == 20.455 + assert sfactors["velocities"] == 20.455 def test_write_bad_scale_factor(self, outfile, universe): errmsg = "scale_factor parsnips is not a float" with pytest.raises(TypeError, match=errmsg): - NCDFWriter(outfile, n_atoms=len(universe.atoms), - scale_velocities="parsnips") - - @pytest.mark.parametrize('stime, slengths, sangles, scoords, svels, sfrcs', ( + NCDFWriter( + outfile, + n_atoms=len(universe.atoms), + scale_velocities="parsnips", + ) + + @pytest.mark.parametrize( + "stime, slengths, sangles, scoords, svels, sfrcs", + ( (-2.0, -2.0, -2.0, -2.0, -2.0, -2.0), (1.0, 1.0, 1.0, 1.0, 1.0, 1.0), - (2.0, 4.0, 8.0, 16.0, 32.0, 64.0) - )) - def test_write_read_write(self, outfile, outfile2, universe, stime, - slengths, sangles, scoords, svels, sfrcs): + (2.0, 4.0, 8.0, 16.0, 32.0, 64.0), + ), + ) + def test_write_read_write( + self, + outfile, + outfile2, + universe, + stime, + slengths, + sangles, + scoords, + svels, + sfrcs, + ): """Write out a file with assorted scale_factors, then read it back in, then write it out to make sure that the new assorted scale_factors have been retained by Write""" - with NCDFWriter(outfile, n_atoms=len(universe.atoms), velocities=True, - forces=True, scale_time=stime, - scale_cell_lengths=slengths, scale_cell_angles=sangles, - scale_coordinates=scoords, scale_velocities=svels, - scale_forces=sfrcs) as W: + with NCDFWriter( + outfile, + n_atoms=len(universe.atoms), + velocities=True, + forces=True, + scale_time=stime, + scale_cell_lengths=slengths, + scale_cell_angles=sangles, + scale_coordinates=scoords, + scale_velocities=svels, + scale_forces=sfrcs, + ) as W: for ts in universe.trajectory: W.write(universe.atoms) @@ -997,46 +1185,70 @@ def test_write_read_write(self, outfile, outfile2, universe, stime, assert sfactors1 == sfactors2 assert len(sfactors1) == 6 - assert sfactors1['time'] == stime - assert sfactors1['cell_lengths'] == slengths - assert sfactors1['cell_angles'] == sangles - assert sfactors1['coordinates'] == scoords - assert sfactors1['velocities'] == svels - assert sfactors1['forces'] == sfrcs + assert sfactors1["time"] == stime + assert sfactors1["cell_lengths"] == slengths + assert sfactors1["cell_angles"] == sangles + assert sfactors1["coordinates"] == scoords + assert sfactors1["velocities"] == svels + assert sfactors1["forces"] == sfrcs # check that the stored values are indeed scaled - assert_almost_equal(universe.trajectory.time / stime, - self.get_variable(outfile, 'time', 0), 4) - assert_almost_equal(universe.dimensions[:3] / slengths, - self.get_variable(outfile, 'cell_lengths', 0), 4) - assert_almost_equal(universe.dimensions[3:] / sangles, - self.get_variable(outfile, 'cell_angles', 0), 4) - assert_almost_equal(universe.atoms.positions / scoords, - self.get_variable(outfile, 'coordinates', 0), 4) - assert_almost_equal(universe.atoms.velocities / svels, - self.get_variable(outfile, 'velocities', 0), 4) + assert_almost_equal( + universe.trajectory.time / stime, + self.get_variable(outfile, "time", 0), + 4, + ) + assert_almost_equal( + universe.dimensions[:3] / slengths, + self.get_variable(outfile, "cell_lengths", 0), + 4, + ) + assert_almost_equal( + universe.dimensions[3:] / sangles, + self.get_variable(outfile, "cell_angles", 0), + 4, + ) + assert_almost_equal( + universe.atoms.positions / scoords, + self.get_variable(outfile, "coordinates", 0), + 4, + ) + assert_almost_equal( + universe.atoms.velocities / svels, + self.get_variable(outfile, "velocities", 0), + 4, + ) # note: kJ/mol -> kcal/mol = 4.184 conversion - assert_almost_equal(universe.atoms.forces / (sfrcs * 4.184), - self.get_variable(outfile, 'forces', 0), 4) + assert_almost_equal( + universe.atoms.forces / (sfrcs * 4.184), + self.get_variable(outfile, "forces", 0), + 4, + ) # check that the individual components were saved/read properly 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.velocities, - universe3.atoms.velocities, 4) - assert_almost_equal(universe.atoms.forces, - universe3.atoms.forces, 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 + ) class TestScipyScaleFactors(TestNCDFWriterScaleFactors): """As above, but netCDF4 is disabled since scaleandmask is different between the two libraries""" + @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 @@ -1047,35 +1259,44 @@ def test_ncdf4_not_present(self, outfile, universe): class TestNCDFWriterUnits(object): """Tests that the writer adheres to AMBER convention units""" + @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir) + 'ncdf-writer-1.ncdf' - - @pytest.mark.parametrize('var, expected', ( - ('coordinates', 'angstrom'), - ('time', 'picosecond'), - ('cell_lengths', 'angstrom'), - ('cell_angles', 'degree'), - ('velocities', 'angstrom/picosecond'), - ('forces', 'kilocalorie/mole/angstrom') - )) + return str(tmpdir) + "ncdf-writer-1.ncdf" + + @pytest.mark.parametrize( + "var, expected", + ( + ("coordinates", "angstrom"), + ("time", "picosecond"), + ("cell_lengths", "angstrom"), + ("cell_angles", "degree"), + ("velocities", "angstrom/picosecond"), + ("forces", "kilocalorie/mole/angstrom"), + ), + ) def test_writer_units(self, outfile, var, expected): - trr = mda.Universe(DLP_CONFIG, format='CONFIG') - - with mda.Writer(outfile, trr.trajectory.n_atoms, velocities=True, - forces=True, format='ncdf') as W: + trr = mda.Universe(DLP_CONFIG, format="CONFIG") + + with mda.Writer( + outfile, + trr.trajectory.n_atoms, + velocities=True, + forces=True, + format="ncdf", + ) as W: for ts in trr.trajectory: W.write(trr) - with netcdf_file(outfile, mode='r') as ncdf: - unit = ncdf.variables[var].units.decode('utf-8') + with netcdf_file(outfile, mode="r") as ncdf: + unit = ncdf.variables[var].units.decode("utf-8") assert_equal(unit, expected) class TestNCDFWriterErrorsWarnings(object): @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir) + 'out.ncdf' + return str(tmpdir) + "out.ncdf" def test_zero_atoms_VE(self, outfile): with pytest.raises(ValueError): diff --git a/testsuite/MDAnalysisTests/coordinates/test_null.py b/testsuite/MDAnalysisTests/coordinates/test_null.py index fc23803258..2990930e67 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_null.py +++ b/testsuite/MDAnalysisTests/coordinates/test_null.py @@ -23,7 +23,7 @@ import MDAnalysis as mda import pytest -from MDAnalysisTests.datafiles import (TPR, XTC) +from MDAnalysisTests.datafiles import TPR, XTC @pytest.fixture() diff --git a/testsuite/MDAnalysisTests/coordinates/test_pdb.py b/testsuite/MDAnalysisTests/coordinates/test_pdb.py index 441a91864d..50219d7b03 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_pdb.py +++ b/testsuite/MDAnalysisTests/coordinates/test_pdb.py @@ -28,31 +28,53 @@ import pytest from MDAnalysisTests import make_Universe from MDAnalysisTests.coordinates.base import _SingleFrameReader -from MDAnalysisTests.coordinates.reference import (RefAdKSmall, - RefAdK) -from MDAnalysisTests.datafiles import (PDB, PDB_small, PDB_multiframe, - PDB_full, PDB_varying, - XPDB_small, PSF, DCD, CONECT, CRD, - INC_PDB, PDB_xlserial, ALIGN, ENT, - PDB_cm, PDB_cm_gz, PDB_cm_bz2, - PDB_mc, PDB_mc_gz, PDB_mc_bz2, - PDB_CRYOEM_BOX, MMTF_NOCRYST, - PDB_HOLE, mol2_molecule, PDB_charges, - CONECT_ERROR,) -from numpy.testing import (assert_equal, - assert_array_almost_equal, - assert_almost_equal, - assert_allclose) - -IGNORE_NO_INFORMATION_WARNING = 'ignore:Found no information for attr:UserWarning' +from MDAnalysisTests.coordinates.reference import RefAdKSmall, RefAdK +from MDAnalysisTests.datafiles import ( + PDB, + PDB_small, + PDB_multiframe, + PDB_full, + PDB_varying, + XPDB_small, + PSF, + DCD, + CONECT, + CRD, + INC_PDB, + PDB_xlserial, + ALIGN, + ENT, + PDB_cm, + PDB_cm_gz, + PDB_cm_bz2, + PDB_mc, + PDB_mc_gz, + PDB_mc_bz2, + PDB_CRYOEM_BOX, + MMTF_NOCRYST, + PDB_HOLE, + mol2_molecule, + PDB_charges, + CONECT_ERROR, +) +from numpy.testing import ( + assert_equal, + assert_array_almost_equal, + assert_almost_equal, + assert_allclose, +) + +IGNORE_NO_INFORMATION_WARNING = ( + "ignore:Found no information for attr:UserWarning" +) @pytest.fixture def dummy_universe_without_elements(): n_atoms = 5 u = make_Universe(size=(n_atoms, 1, 1), trajectory=True) - u.add_TopologyAttr('resnames', ['RES']) - u.add_TopologyAttr('names', ['C1', 'O2', 'N3', 'S4', 'NA']) + u.add_TopologyAttr("resnames", ["RES"]) + u.add_TopologyAttr("names", ["C1", "O2", "N3", "S4", "NA"]) u.dimensions = [42, 42, 42, 90, 90, 90] return u @@ -70,109 +92,140 @@ def setUp(self): def test_uses_PDBReader(self): from MDAnalysis.coordinates.PDB import PDBReader - assert isinstance(self.universe.trajectory, PDBReader), "failed to choose PDBReader" + assert isinstance( + self.universe.trajectory, PDBReader + ), "failed to choose PDBReader" def test_dimensions(self): assert_almost_equal( - self.universe.trajectory.ts.dimensions, RefAdKSmall.ref_unitcell, + self.universe.trajectory.ts.dimensions, + RefAdKSmall.ref_unitcell, self.prec, - "PDBReader failed to get unitcell dimensions from CRYST1") + "PDBReader failed to get unitcell dimensions from CRYST1", + ) def test_ENT(self): from MDAnalysis.coordinates.PDB import PDBReader + self.universe = mda.Universe(ENT) - assert isinstance(self.universe.trajectory, PDBReader), "failed to choose PDBReader" + assert isinstance( + self.universe.trajectory, PDBReader + ), "failed to choose PDBReader" class TestPDBMetadata(object): - header = 'HYDROLASE 11-MAR-12 4E43' - title = ['HIV PROTEASE (PR) DIMER WITH ACETATE IN EXO SITE AND PEPTIDE ' - 'IN ACTIVE', '2 SITE'] - compnd = ['MOL_ID: 1;', - '2 MOLECULE: PROTEASE;', - '3 CHAIN: A, B;', - '4 ENGINEERED: YES;', - '5 MUTATION: YES;', - '6 MOL_ID: 2;', - '7 MOLECULE: RANDOM PEPTIDE;', - '8 CHAIN: C;', - '9 ENGINEERED: YES;', - '10 OTHER_DETAILS: UNKNOWN IMPURITY', ] + header = "HYDROLASE 11-MAR-12 4E43" + title = [ + "HIV PROTEASE (PR) DIMER WITH ACETATE IN EXO SITE AND PEPTIDE " + "IN ACTIVE", + "2 SITE", + ] + compnd = [ + "MOL_ID: 1;", + "2 MOLECULE: PROTEASE;", + "3 CHAIN: A, B;", + "4 ENGINEERED: YES;", + "5 MUTATION: YES;", + "6 MOL_ID: 2;", + "7 MOLECULE: RANDOM PEPTIDE;", + "8 CHAIN: C;", + "9 ENGINEERED: YES;", + "10 OTHER_DETAILS: UNKNOWN IMPURITY", + ] num_remarks = 333 # only first 5 remarks for comparison nmax_remarks = 5 remarks = [ - '2', - '2 RESOLUTION. 1.54 ANGSTROMS.', - '3', - '3 REFINEMENT.', - '3 PROGRAM : REFMAC 5.5.0110', + "2", + "2 RESOLUTION. 1.54 ANGSTROMS.", + "3", + "3 REFINEMENT.", + "3 PROGRAM : REFMAC 5.5.0110", ] @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def universe(): return mda.Universe(PDB_full) def test_HEADER(self, universe): - assert_equal(universe.trajectory.header, - self.header, - err_msg="HEADER record not correctly parsed") + assert_equal( + universe.trajectory.header, + self.header, + err_msg="HEADER record not correctly parsed", + ) def test_TITLE(self, universe): try: title = universe.trajectory.title except AttributeError: raise AssertionError("Reader does not have a 'title' attribute.") - assert_equal(len(title), - 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): - assert_equal(parsed, - reference, - err_msg="TITLE line {0} do not match".format(lineno)) + assert_equal( + len(title), + 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 + ): + assert_equal( + parsed, + reference, + err_msg="TITLE line {0} do not match".format(lineno), + ) def test_COMPND(self, universe): try: compound = universe.trajectory.compound except AttributeError: raise AssertionError( - "Reader does not have a 'compound' attribute.") - assert_equal(len(compound), - len(self.compnd), - err_msg="COMPND does not contain same number of lines") - for lineno, (parsed, reference) in enumerate(zip(compound, - self.compnd), - start=1): - assert_equal(parsed, - reference, - err_msg="COMPND line {0} do not match".format(lineno)) + "Reader does not have a 'compound' attribute." + ) + assert_equal( + len(compound), + len(self.compnd), + err_msg="COMPND does not contain same number of lines", + ) + for lineno, (parsed, reference) in enumerate( + zip(compound, self.compnd), start=1 + ): + assert_equal( + parsed, + reference, + err_msg="COMPND line {0} do not match".format(lineno), + ) def test_REMARK(self, universe): try: remarks = universe.trajectory.remarks except AttributeError: raise AssertionError("Reader does not have a 'remarks' attribute.") - assert_equal(len(remarks), - self.num_remarks, - err_msg="REMARK does not contain same number of lines") + assert_equal( + len(remarks), + self.num_remarks, + err_msg="REMARK does not contain same number of lines", + ) # only look at the first 5 entries for lineno, (parsed, reference) in enumerate( - zip(remarks[:self.nmax_remarks], - self.remarks[:self.nmax_remarks]), - start=1): - assert_equal(parsed, - reference, - err_msg="REMARK line {0} do not match".format(lineno)) + zip( + remarks[: self.nmax_remarks], self.remarks[: self.nmax_remarks] + ), + start=1, + ): + assert_equal( + parsed, + reference, + err_msg="REMARK line {0} do not match".format(lineno), + ) 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 @@ -181,7 +234,8 @@ def test_long_resSeq(self): # it checks that it can read a 5-digit resid self.universe = mda.Universe(XPDB_small, topology_format="XPDB") u = self.universe.select_atoms( - 'resid 1 or resid 10 or resid 100 or resid 1000 or resid 10000') + "resid 1 or resid 10 or resid 100 or resid 1000 or resid 10000" + ) assert_equal(u[4].resid, 10000, "can't read a five digit resid") @@ -211,10 +265,7 @@ def universe4(self): def universe5(self): return mda.Universe(mol2_molecule) - @pytest.fixture(params=[ - [PDB_CRYOEM_BOX, None], - [MMTF_NOCRYST, None] - ]) + @pytest.fixture(params=[[PDB_CRYOEM_BOX, None], [MMTF_NOCRYST, None]]) def universe_and_expected_dims(self, request): """ File with meaningless CRYST1 record and expected dimensions. @@ -226,7 +277,9 @@ 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): @@ -234,41 +287,51 @@ def u_no_ids(self): # else the PDB writer expects to avoid issuing warnings. universe = make_Universe( [ - 'names', 'resids', 'resnames', 'altLocs', - 'segids', 'occupancies', 'tempfactors', + "names", + "resids", + "resnames", + "altLocs", + "segids", + "occupancies", + "tempfactors", ], trajectory=True, ) - universe.add_TopologyAttr('icodes', [' '] * len(universe.residues)) - universe.add_TopologyAttr('record_types', ['ATOM'] * len(universe.atoms)) + universe.add_TopologyAttr("icodes", [" "] * len(universe.residues)) + universe.add_TopologyAttr( + "record_types", ["ATOM"] * len(universe.atoms) + ) universe.dimensions = [10, 10, 10, 90, 90, 90] return universe @pytest.fixture def u_no_resnames(self): - return make_Universe(['names', 'resids'], trajectory=True) + return make_Universe(["names", "resids"], trajectory=True) @pytest.fixture def u_no_resids(self): - return make_Universe(['names', 'resnames'], trajectory=True) + return make_Universe(["names", "resnames"], trajectory=True) @pytest.fixture def u_no_names(self): - return make_Universe(['resids', 'resnames'], trajectory=True) + return make_Universe(["resids", "resnames"], trajectory=True) def test_writer(self, universe, outfile): "Test writing from a single frame PDB file to a PDB file." "" universe.atoms.write(outfile) u = mda.Universe(PSF, outfile) - assert_almost_equal(u.atoms.positions, - universe.atoms.positions, self.prec, - err_msg="Writing PDB file with PDBWriter " - "does not reproduce original coordinates") + assert_almost_equal( + u.atoms.positions, + universe.atoms.positions, + self.prec, + err_msg="Writing PDB file with PDBWriter " + "does not reproduce original coordinates", + ) def test_writer_no_resnames(self, u_no_resnames, outfile): u_no_resnames.atoms.write(outfile) u = mda.Universe(outfile) - expected = np.array(['UNK'] * u_no_resnames.atoms.n_atoms) + expected = np.array(["UNK"] * u_no_resnames.atoms.n_atoms) assert_equal(u.atoms.resnames, expected) def test_writer_no_resids(self, u_no_resids, outfile): @@ -280,25 +343,25 @@ def test_writer_no_resids(self, u_no_resids, outfile): def test_writer_no_atom_names(self, u_no_names, outfile): u_no_names.atoms.write(outfile) u = mda.Universe(outfile) - expected = np.array(['X'] * u_no_names.atoms.n_atoms) + expected = np.array(["X"] * u_no_names.atoms.n_atoms) assert_equal(u.atoms.names, expected) def test_writer_no_altlocs(self, u_no_names, outfile): u_no_names.atoms.write(outfile) u = mda.Universe(outfile) - expected = np.array([''] * u_no_names.atoms.n_atoms) + expected = np.array([""] * u_no_names.atoms.n_atoms) assert_equal(u.atoms.altLocs, expected) def test_writer_no_icodes(self, u_no_names, outfile): u_no_names.atoms.write(outfile) u = mda.Universe(outfile) - expected = np.array([''] * u_no_names.atoms.n_atoms) + expected = np.array([""] * u_no_names.atoms.n_atoms) assert_equal(u.atoms.icodes, expected) def test_writer_no_segids(self, u_no_names, outfile): u_no_names.atoms.write(outfile) u = mda.Universe(outfile) - expected = np.array(['X'] * u_no_names.atoms.n_atoms) + expected = np.array(["X"] * u_no_names.atoms.n_atoms) assert_equal([atom.segid for atom in u.atoms], expected) def test_writer_no_occupancies(self, u_no_names, outfile): @@ -318,12 +381,14 @@ def test_write_single_frame_Writer(self, universe2, outfile): MDAnalysis.Writer (Issue 105)""" u = universe2 u.trajectory[50] - with mda.Writer(outfile) as W: - W.write(u.select_atoms('all')) + with mda.Writer(outfile) as W: + W.write(u.select_atoms("all")) u2 = mda.Universe(outfile) - assert_equal(u2.trajectory.n_frames, - 1, - err_msg="The number of frames should be 1.") + assert_equal( + u2.trajectory.n_frames, + 1, + err_msg="The number of frames should be 1.", + ) def test_write_single_frame_AtomGroup(self, universe2, outfile): """Test writing a single frame from a DCD trajectory to a PDB using @@ -332,13 +397,19 @@ def test_write_single_frame_AtomGroup(self, universe2, outfile): u.trajectory[50] u.atoms.write(outfile) u2 = mda.Universe(PSF, outfile) - assert_equal(u2.trajectory.n_frames, - 1, - err_msg="Output PDB should only contain a single frame") - assert_almost_equal(u2.atoms.positions, u.atoms.positions, - self.prec, err_msg="Written coordinates do not " - "agree with original coordinates from frame %d" % - u.trajectory.frame) + assert_equal( + u2.trajectory.n_frames, + 1, + err_msg="Output PDB should only contain a single frame", + ) + assert_almost_equal( + u2.atoms.positions, + u.atoms.positions, + self.prec, + err_msg="Written coordinates do not " + "agree with original coordinates from frame %d" + % u.trajectory.frame, + ) def test_write_nodims(self, universe_and_expected_dims, outfile): """ @@ -362,25 +433,28 @@ def test_write_nodims(self, universe_and_expected_dims, outfile): with pytest.warns(UserWarning, match=expected_msg): u.atoms.write(outfile) - 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." + ): uout = mda.Universe(outfile) assert uout.dimensions is None, "Problem with default box." assert_equal( - uout.trajectory.n_frames, 1, - err_msg="Output PDB should only contain a single frame" + uout.trajectory.n_frames, + 1, + err_msg="Output PDB should only contain a single frame", ) assert_almost_equal( - u.atoms.positions, uout.atoms.positions, + u.atoms.positions, + 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): """Test that illegal PDB coordinates (x <= -999.9995 A) are caught with ValueError (Issue 57)""" @@ -413,16 +487,17 @@ def test_check_HEADER_TITLE_multiframe(self, universe2, outfile): got_header = 0 got_title = 0 for line in f: - if line.startswith('HEADER'): + if line.startswith("HEADER"): got_header += 1 assert got_header <= 1, "There should be only one HEADER." - elif line.startswith('TITLE'): + elif line.startswith("TITLE"): got_title += 1 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): + @pytest.mark.parametrize("startframe,maxframes", [(0, 12), (9997, 12)]) + 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") @@ -439,7 +514,7 @@ def get_MODEL_lines(filename): MODEL_lines = list(get_MODEL_lines(outfile)) assert len(MODEL_lines) == maxframes - for model, line in enumerate(MODEL_lines, start=startframe+1): + for model, line in enumerate(MODEL_lines, start=startframe + 1): # test that only the right-most 4 digits are stored (rest must be space) # line[10:14] == '9999' or ' 1' @@ -449,14 +524,13 @@ def get_MODEL_lines(filename): # test number (only last 4 digits) assert int(line[10:14]) == model % 10000 - @pytest.mark.parametrize("bad_chainid", - ['@', '', 'AA']) + @pytest.mark.parametrize("bad_chainid", ["@", "", "AA"]) def test_chainid_validated(self, universe3, outfile, bad_chainid): """ Check that an atom's chainID is set to 'X' if the chainID does not confirm to standards (issue #2224) """ - default_id = 'X' + default_id = "X" u = universe3 u.atoms.chainIDs = bad_chainid u.atoms.write(outfile) @@ -493,16 +567,18 @@ 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 len(u_hetatms) == len(written_atoms), "mismatched HETATM number" + 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. @@ -510,19 +586,19 @@ def test_default_atom_record_type_written(self, universe5, tmpdir, u = universe5 - expected_msg = ("Found no information for attr: " - "'record_types' Using default value of 'ATOM'") + expected_msg = ( + "Found no information for attr: " + "'record_types' Using default value of 'ATOM'" + ) with pytest.warns(UserWarning, match=expected_msg): u.atoms.write(outfile) written = mda.Universe(outfile) - assert len(u.atoms) == len(written.atoms), \ - "mismatched number of atoms" + assert len(u.atoms) == len(written.atoms), "mismatched number of atoms" atms = written.select_atoms("record_type ATOM") - assert len(atms.atoms) == len(u.atoms), \ - "mismatched ATOM number" + assert len(atms.atoms) == len(u.atoms), "mismatched ATOM number" hetatms = written.select_atoms("record_type HETATM") assert len(hetatms.atoms) == 0, "mismatched HETATM number" @@ -533,10 +609,12 @@ def test_abnormal_record_type(self, universe5, tmpdir, outfile): neither ATOM or HETATM. """ u = universe5 - u.add_TopologyAttr('record_type', ['ABNORM']*len(u.atoms)) + u.add_TopologyAttr("record_type", ["ABNORM"] * len(u.atoms)) - expected_msg = ("Found ABNORM for the record type, but only " - "allowed types are ATOM or HETATM") + expected_msg = ( + "Found ABNORM for the record type, but only " + "allowed types are ATOM or HETATM" + ) with pytest.raises(ValueError, match=expected_msg): u.atoms.write(outfile) @@ -559,14 +637,14 @@ def test_no_reindex_bonds(self, universe, outfile): record match the non-reindexed atoms. """ universe.atoms.ids = universe.atoms.ids + 23 - universe.atoms.write(outfile, reindex=False, bonds='all') + universe.atoms.write(outfile, reindex=False, bonds="all") with open(outfile) as infile: for line in infile: - if line.startswith('CONECT'): + if line.startswith("CONECT"): assert line.strip() == "CONECT 23 24 25 26 27" break else: - raise AssertError('No CONECT record fond in the output.') + raise AssertError("No CONECT record fond in the output.") @pytest.mark.filterwarnings(IGNORE_NO_INFORMATION_WARNING) def test_reindex(self, universe, outfile): @@ -586,43 +664,57 @@ def test_no_reindex_missing_ids(self, u_no_ids, outfile): then an exception is raised. """ # Making sure AG.ids is indeed missing - assert not hasattr(u_no_ids.atoms, 'ids') + assert not hasattr(u_no_ids.atoms, "ids") with pytest.raises(mda.exceptions.NoDataError): u_no_ids.atoms.write(outfile, reindex=False) class TestMultiPDBReader(object): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def multiverse(): return mda.Universe(PDB_multiframe, guess_bonds=True) @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def conect(): return mda.Universe(CONECT, guess_bonds=True) def test_n_frames(self, multiverse): - assert_equal(multiverse.trajectory.n_frames, 24, - "Wrong number of frames read from PDB muliple model file") + assert_equal( + multiverse.trajectory.n_frames, + 24, + "Wrong number of frames read from PDB muliple model file", + ) def test_n_atoms_frame(self, multiverse): u = multiverse desired = 392 for frame in u.trajectory: - assert_equal(len(u.atoms), desired, err_msg="The number of atoms " - "in the Universe (%d) does not" " match the number " - "of atoms in the test case (%d) at frame %d" % ( - len(u.atoms), desired, u.trajectory.frame)) + assert_equal( + len(u.atoms), + desired, + err_msg="The number of atoms " + "in the Universe (%d) does not" + " match the number " + "of atoms in the test case (%d) at frame %d" + % (len(u.atoms), desired, u.trajectory.frame), + ) def test_rewind(self, multiverse): u = multiverse u.trajectory[11] - assert_equal(u.trajectory.ts.frame, 11, - "Failed to forward to 11th frame (frame index 11)") + assert_equal( + u.trajectory.ts.frame, + 11, + "Failed to forward to 11th frame (frame index 11)", + ) u.trajectory.rewind() - assert_equal(u.trajectory.ts.frame, 0, - "Failed to rewind to 0th frame (frame index 0)") + assert_equal( + u.trajectory.ts.frame, + 0, + "Failed to rewind to 0th frame (frame index 0)", + ) def test_iteration(self, multiverse): u = multiverse @@ -634,25 +726,29 @@ def test_iteration(self, multiverse): for ts in u.trajectory: frames.append(ts) assert_equal( - len(frames), u.trajectory.n_frames, + len(frames), + u.trajectory.n_frames, "iterated number of frames %d is not the expected number %d; " - "trajectory iterator fails to rewind" % - (len(frames), u.trajectory.n_frames)) + "trajectory iterator fails to rewind" + % (len(frames), u.trajectory.n_frames), + ) def test_slice_iteration(self, multiverse): u = multiverse frames = [] for ts in u.trajectory[4:-2:4]: frames.append(ts.frame) - assert_equal(np.array(frames), - np.arange(u.trajectory.n_frames)[4:-2:4], - err_msg="slicing did not produce the expected frames") + assert_equal( + np.array(frames), + np.arange(u.trajectory.n_frames)[4:-2:4], + err_msg="slicing did not produce the expected frames", + ) def test_conect_bonds_conect(self, tmpdir, conect): assert_equal(len(conect.atoms), 1890) assert_equal(len(conect.bonds), 1922) - outfile = str(tmpdir.join('test-pdb-hbonds.pdb')) + outfile = str(tmpdir.join("test-pdb-hbonds.pdb")) conect.atoms.write(outfile, bonds="conect") u1 = mda.Universe(outfile, guess_bonds=True) @@ -660,7 +756,7 @@ def test_conect_bonds_conect(self, tmpdir, conect): assert_equal(len(u1.bonds), 1922) def test_conect_error(self): - with pytest.warns(UserWarning, match='CONECT records was corrupt'): + with pytest.warns(UserWarning, match="CONECT records was corrupt"): u = mda.Universe(CONECT_ERROR) def test_numconnections(self, multiverse): @@ -668,31 +764,34 @@ def test_numconnections(self, multiverse): # the bond list is sorted - so swaps in input pdb sequence should not # be a problem - desired = [[48, 365], - [99, 166], - [166, 99], - [249, 387], - [313, 331], - [331, 313, 332, 340], - [332, 331, 333, 338, 341], - [333, 332, 334, 342, 343], - [334, 333, 335, 344, 345], - [335, 334, 336, 337], - [336, 335], - [337, 335, 346, 347, 348], [338, 332, 339, 349], - [339, 338], - [340, 331], - [341, 332], - [342, 333], - [343, 333], - [344, 334], - [345, 334], - [346, 337], - [347, 337], - [348, 337], - [349, 338], - [365, 48], - [387, 249]] + desired = [ + [48, 365], + [99, 166], + [166, 99], + [249, 387], + [313, 331], + [331, 313, 332, 340], + [332, 331, 333, 338, 341], + [333, 332, 334, 342, 343], + [334, 333, 335, 344, 345], + [335, 334, 336, 337], + [336, 335], + [337, 335, 346, 347, 348], + [338, 332, 339, 349], + [339, 338], + [340, 331], + [341, 332], + [342, 333], + [343, 333], + [344, 334], + [345, 334], + [346, 337], + [347, 337], + [348, 337], + [349, 338], + [365, 48], + [387, 249], + ] def helper(atoms, bonds): """ @@ -711,15 +810,28 @@ def helper(atoms, bonds): atoms = sorted([a.index for a in atoms]) - conect = [([a, ] + sorted(con[a])) for a in atoms if a in con] + conect = [ + ( + [ + a, + ] + + sorted(con[a]) + ) + for a in atoms + if a in con + ] conect = [[a + 1 for a in c] for c in conect] return conect conect = helper(u.atoms, [b for b in u.bonds if not b.is_guessed]) - assert_equal(conect, desired, err_msg="The bond list does not match " - "the test reference; len(actual) is %d, len(desired) " - "is %d" % (len(u._topology.bonds.values), len(desired))) + assert_equal( + conect, + desired, + err_msg="The bond list does not match " + "the test reference; len(actual) is %d, len(desired) " + "is %d" % (len(u._topology.bonds.values), len(desired)), + ) def test_conect_bonds_all(tmpdir): @@ -728,7 +840,7 @@ def test_conect_bonds_all(tmpdir): assert_equal(len(conect.atoms), 1890) assert_equal(len(conect.bonds), 1922) - outfile = os.path.join(str(tmpdir), 'pdb-connect-bonds.pdb') + outfile = os.path.join(str(tmpdir), "pdb-connect-bonds.pdb") conect.atoms.write(outfile, bonds="all") u2 = mda.Universe(outfile, guess_bonds=True) @@ -743,7 +855,7 @@ def test_write_bonds_partial(tmpdir): # grab all atoms with bonds ag = (u.atoms.bonds.atom1 + u.atoms.bonds.atom2).unique - outfile = os.path.join(str(tmpdir), 'test.pdb') + outfile = os.path.join(str(tmpdir), "test.pdb") ag.write(outfile) u2 = mda.Universe(outfile) @@ -760,8 +872,8 @@ def test_write_bonds_with_100000_ag_index(tmpdir): ag = u.atoms ag.ids = ag.ids + 100000 - with pytest.warns(UserWarning, match='Atom with index'): - outfile = os.path.join(str(tmpdir), 'test.pdb') + with pytest.warns(UserWarning, match="Atom with index"): + outfile = os.path.join(str(tmpdir), "test.pdb") ag.write(outfile, reindex=False) @@ -788,13 +900,13 @@ def universe2(): @staticmethod @pytest.fixture def outfile(tmpdir): - return os.path.join(str(tmpdir), 'multiwriter-test-1.pdb') + return os.path.join(str(tmpdir), "multiwriter-test-1.pdb") def test_write_atomselection(self, multiverse, outfile): """Test if multiframe writer can write selected frames for an atomselection.""" u = multiverse - group = u.select_atoms('name CA', 'name C') + group = u.select_atoms("name CA", "name C") desired_group = 56 desired_frames = 6 pdb = mda.Writer(outfile, multiframe=True, start=12, step=2) @@ -802,15 +914,21 @@ def test_write_atomselection(self, multiverse, outfile): pdb.write(group) pdb.close() u2 = mda.Universe(outfile) - assert_equal(len(u2.atoms), desired_group, - err_msg="MultiPDBWriter trajectory written for an " - "AtomGroup contains %d atoms, it should contain %d" % ( - len(u2.atoms), desired_group)) + assert_equal( + len(u2.atoms), + desired_group, + err_msg="MultiPDBWriter trajectory written for an " + "AtomGroup contains %d atoms, it should contain %d" + % (len(u2.atoms), desired_group), + ) - assert_equal(len(u2.trajectory), desired_frames, - err_msg="MultiPDBWriter trajectory written for an " - "AtomGroup contains %d frames, it should have %d" % ( - len(u.trajectory), desired_frames)) + assert_equal( + len(u2.trajectory), + desired_frames, + err_msg="MultiPDBWriter trajectory written for an " + "AtomGroup contains %d frames, it should have %d" + % (len(u.trajectory), desired_frames), + ) def test_write_all_timesteps(self, multiverse, outfile): """ @@ -818,22 +936,28 @@ def test_write_all_timesteps(self, multiverse, outfile): for an atomselection) """ u = multiverse - group = u.select_atoms('name CA', 'name C') + group = u.select_atoms("name CA", "name C") desired_group = 56 desired_frames = 6 with mda.Writer(outfile, multiframe=True, start=12, step=2) as W: W.write_all_timesteps(group) u2 = mda.Universe(outfile) - assert_equal(len(u2.atoms), desired_group, - err_msg="MultiPDBWriter trajectory written for an " - "AtomGroup contains %d atoms, it should contain %d" % ( - len(u2.atoms), desired_group)) + assert_equal( + len(u2.atoms), + desired_group, + err_msg="MultiPDBWriter trajectory written for an " + "AtomGroup contains %d atoms, it should contain %d" + % (len(u2.atoms), desired_group), + ) - assert_equal(len(u2.trajectory), desired_frames, - err_msg="MultiPDBWriter trajectory written for an " - "AtomGroup contains %d frames, it should have %d" % ( - len(u.trajectory), desired_frames)) + assert_equal( + len(u2.trajectory), + desired_frames, + err_msg="MultiPDBWriter trajectory written for an " + "AtomGroup contains %d frames, it should have %d" + % (len(u.trajectory), desired_frames), + ) with open(outfile, "r") as f: lines = f.read() @@ -845,7 +969,7 @@ def test_write_loop(self, multiverse, outfile): for an atomselection) """ u = multiverse - group = u.select_atoms('name CA', 'name C') + group = u.select_atoms("name CA", "name C") desired_group = 56 desired_frames = 6 @@ -854,15 +978,21 @@ def test_write_loop(self, multiverse, outfile): W.write(group) u2 = mda.Universe(outfile) - assert_equal(len(u2.atoms), desired_group, - err_msg="MultiPDBWriter trajectory written for an " - f"AtomGroup contains {len(u2.atoms)} atoms, " - f"it should contain {desired_group}") + assert_equal( + len(u2.atoms), + desired_group, + err_msg="MultiPDBWriter trajectory written for an " + f"AtomGroup contains {len(u2.atoms)} atoms, " + f"it should contain {desired_group}", + ) - assert_equal(len(u2.trajectory), desired_frames, - err_msg="MultiPDBWriter trajectory written for an " - f"AtomGroup contains {len(u.trajectory)} " - f"frames, it should have {desired_frames}") + assert_equal( + len(u2.trajectory), + desired_frames, + err_msg="MultiPDBWriter trajectory written for an " + f"AtomGroup contains {len(u.trajectory)} " + f"frames, it should have {desired_frames}", + ) with open(outfile, "r") as f: lines = f.read() @@ -878,42 +1008,52 @@ def test_write_atoms(self, universe2, outfile): W.write(u.atoms) u0 = mda.Universe(outfile) - assert_equal(u0.trajectory.n_frames, - 2, - err_msg="The number of frames should be 2.") + assert_equal( + u0.trajectory.n_frames, + 2, + err_msg="The number of frames should be 2.", + ) class TestPDBReaderBig(RefAdK): prec = 6 @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def universe(): return mda.Universe(PDB) def test_load_pdb(self, universe): U = universe - 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], "Atom selections") + 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], + "Atom selections", + ) def test_selection(self, universe): - na = universe.select_atoms('resname NA+') - assert_equal(len(na), self.ref_Na_sel_size, - "Atom selection of last atoms in file") + na = universe.select_atoms("resname NA+") + assert_equal( + len(na), + self.ref_Na_sel_size, + "Atom selection of last atoms in file", + ) def test_n_atoms(self, universe): - assert_equal(universe.trajectory.n_atoms, self.ref_n_atoms, - "wrong number of atoms") + assert_equal( + universe.trajectory.n_atoms, + self.ref_n_atoms, + "wrong number of atoms", + ) def test_n_frames(self, universe): - assert_equal(universe.trajectory.n_frames, 1, - "wrong number of frames") + assert_equal(universe.trajectory.n_frames, 1, "wrong number of frames") def test_time(self, universe): - assert_equal(universe.trajectory.time, 0.0, - "wrong time of the frame") + assert_equal(universe.trajectory.time, 0.0, "wrong time of the frame") def test_frame(self, universe): assert_equal(universe.trajectory.frame, 0, "wrong frame number") @@ -924,37 +1064,48 @@ def test_dt(self, universe): assert_equal(universe.trajectory.dt, 1.0) def test_coordinates(self, universe): - A10CA = universe.select_atoms('name CA')[10] - assert_almost_equal(A10CA.position, - self.ref_coordinates['A10CA'], - self.prec, - err_msg="wrong coordinates for A10:CA") + A10CA = universe.select_atoms("name CA")[10] + assert_almost_equal( + A10CA.position, + self.ref_coordinates["A10CA"], + self.prec, + err_msg="wrong coordinates for A10:CA", + ) def test_distances(self, universe): - NTERM = universe.select_atoms('name N')[0] - CTERM = universe.select_atoms('name C')[-1] + NTERM = universe.select_atoms("name N")[0] + CTERM = universe.select_atoms("name C")[-1] d = mda.lib.mdamath.norm(NTERM.position - CTERM.position) - assert_almost_equal(d, self.ref_distances['endtoend'], self.prec, - err_msg="wrong distance between M1:N and G214:C") + assert_almost_equal( + d, + self.ref_distances["endtoend"], + self.prec, + err_msg="wrong distance between M1:N and G214:C", + ) def test_selection(self, universe): - na = universe.select_atoms('resname NA+') - assert_equal(len(na), self.ref_Na_sel_size, - "Atom selection of last atoms in file") + na = universe.select_atoms("resname NA+") + assert_equal( + len(na), + self.ref_Na_sel_size, + "Atom selection of last atoms in file", + ) def test_unitcell(self, universe): assert_array_almost_equal( universe.dimensions, self.ref_unitcell, self.prec, - err_msg="unit cell dimensions (rhombic dodecahedron), issue 60") + err_msg="unit cell dimensions (rhombic dodecahedron), issue 60", + ) def test_volume(self, universe): assert_almost_equal( universe.coord.volume, self.ref_volume, 0, - err_msg="wrong volume for unitcell (rhombic dodecahedron)") + err_msg="wrong volume for unitcell (rhombic dodecahedron)", + ) def test_n_residues(self, universe): # Should have first 10000 residues, then another 1302 @@ -968,20 +1119,27 @@ def test_first_residue(self, universe): class TestPDBVaryingOccTmp: @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def u(): return mda.Universe(PDB_varying) def test_ts_data_keys(self, u): ts = u.trajectory.ts - assert 'occupancy' in ts.data - assert 'tempfactor' in ts.data - - @pytest.mark.parametrize('attr,ag_attr,vals', [ - ('occupancy', 'occupancies', [[1.0, 0.0], [0.9, 0.0], [0.0, 0.0]]), - ('tempfactor', 'tempfactors', [[23.44, 1.0], [24.44, 23.44], [1.0, 23.44]]), - ]) + assert "occupancy" in ts.data + assert "tempfactor" in ts.data + + @pytest.mark.parametrize( + "attr,ag_attr,vals", + [ + ("occupancy", "occupancies", [[1.0, 0.0], [0.9, 0.0], [0.0, 0.0]]), + ( + "tempfactor", + "tempfactors", + [[23.44, 1.0], [24.44, 23.44], [1.0, 23.44]], + ), + ], + ) def test_varying_attrs(self, u, attr, ag_attr, vals): u.trajectory[0] assert_allclose(u.trajectory.ts.data[attr], vals[0]) @@ -1002,8 +1160,9 @@ class TestIncompletePDB(object): Reads an incomplete (but still intelligible) PDB file """ + @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def u(): return mda.Universe(INC_PDB) @@ -1011,32 +1170,38 @@ def test_natoms(self, u): assert_equal(len(u.atoms), 3) def test_coords(self, u): - assert_array_almost_equal(u.atoms.positions, - np.array([[111.2519989, 98.3730011, - 98.18699646], - [111.20300293, 101.74199677, - 96.43000031], [107.60700226, - 102.96800232, - 96.31600189]], - dtype=np.float32)) + assert_array_almost_equal( + u.atoms.positions, + np.array( + [ + [111.2519989, 98.3730011, 98.18699646], + [111.20300293, 101.74199677, 96.43000031], + [107.60700226, 102.96800232, 96.31600189], + ], + dtype=np.float32, + ), + ) def test_dims(self, u): - assert_array_almost_equal(u.dimensions, - np.array([216.48899841, 216.48899841, - 216.48899841, 90., 90., 90.], - dtype=np.float32)) + assert_array_almost_equal( + u.dimensions, + np.array( + [216.48899841, 216.48899841, 216.48899841, 90.0, 90.0, 90.0], + dtype=np.float32, + ), + ) def test_names(self, u): - assert all(u.atoms.names == 'CA') + assert all(u.atoms.names == "CA") def test_residues(self, u): assert_equal(len(u.residues), 3) def test_resnames(self, u): assert_equal(len(u.atoms.resnames), 3) - assert 'VAL' in u.atoms.resnames - assert 'LYS' in u.atoms.resnames - assert 'PHE' in u.atoms.resnames + assert "VAL" in u.atoms.resnames + assert "LYS" in u.atoms.resnames + assert "PHE" in u.atoms.resnames def test_reading_trajectory(self, u): counter = 0 @@ -1047,8 +1212,9 @@ def test_reading_trajectory(self, u): class TestPDBXLSerial(object): """For Issue #446""" + @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def u(): return mda.Universe(PDB_xlserial) @@ -1066,6 +1232,7 @@ def test_serials(self, u): class TestPSF_CRDReader(_SingleFrameReader): __test__ = True + def setUp(self): self.universe = mda.Universe(PSF, CRD) self.prec = 5 # precision in CRD (at least we are writing %9.5f) @@ -1081,7 +1248,9 @@ def setUp(self): def test_uses_PDBReader(self): from MDAnalysis.coordinates.PDB import PDBReader - assert isinstance(self.universe.trajectory, PDBReader), "failed to choose PDBReader" + assert isinstance( + self.universe.trajectory, PDBReader + ), "failed to choose PDBReader" def test_write_occupancies(tmpdir): @@ -1089,7 +1258,7 @@ def test_write_occupancies(tmpdir): u = mda.Universe(PDB_small) u.atoms.occupancies = 0.12 - outfile = str(tmpdir.join('occ.pdb')) + outfile = str(tmpdir.join("occ.pdb")) u.atoms.write(outfile) @@ -1099,48 +1268,70 @@ def test_write_occupancies(tmpdir): class TestWriterAlignments(object): - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def writtenstuff(self, tmpdir_factory): u = mda.Universe(ALIGN) - outfile = str(tmpdir_factory.mktemp('pdb').join('nucl.pdb')) + outfile = str(tmpdir_factory.mktemp("pdb").join("nucl.pdb")) u.atoms.write(outfile) with open(outfile) as fh: return fh.readlines() def test_atomname_alignment(self, writtenstuff): # Our PDBWriter adds some stuff up top, so line 1 happens at [9] - refs = ("ATOM 1 H5T", - "ATOM 2 CA ", - "ATOM 3 CA ", - "ATOM 4 H5''",) + refs = ( + "ATOM 1 H5T", + "ATOM 2 CA ", + "ATOM 3 CA ", + "ATOM 4 H5''", + ) for written, reference in zip(writtenstuff[9:], refs): assert_equal(written[:16], reference) def test_atomtype_alignment(self, writtenstuff): - result_line = ("ATOM 1 H5T GUA X 1 7.974 6.430 9.561" - " 1.00 0.00 RNAA \n") + result_line = ( + "ATOM 1 H5T GUA X 1 7.974 6.430 9.561" + " 1.00 0.00 RNAA \n" + ) assert_equal(writtenstuff[9], result_line) -@pytest.mark.parametrize('atom, refname', ((mda.coordinates.PDB.Pair('ASP', 'CA'), ' CA '), # Regular protein carbon alpha - (mda.coordinates.PDB.Pair('GLU', 'OE1'), ' OE1'), - (mda.coordinates.PDB.Pair('MSE', 'SE'), 'SE '), # Selenium like in 4D3L - (mda.coordinates.PDB.Pair('CA', 'CA'), 'CA '), # Calcium like in 4D3L - (mda.coordinates.PDB.Pair('HDD', 'FE'), 'FE '), # Iron from a heme like in 1GGE - (mda.coordinates.PDB.Pair('PLC', 'P'), ' P '), # Lipid phosphorus (1EIN) -)) +@pytest.mark.parametrize( + "atom, refname", + ( + ( + mda.coordinates.PDB.Pair("ASP", "CA"), + " CA ", + ), # Regular protein carbon alpha + (mda.coordinates.PDB.Pair("GLU", "OE1"), " OE1"), + ( + mda.coordinates.PDB.Pair("MSE", "SE"), + "SE ", + ), # Selenium like in 4D3L + (mda.coordinates.PDB.Pair("CA", "CA"), "CA "), # Calcium like in 4D3L + ( + mda.coordinates.PDB.Pair("HDD", "FE"), + "FE ", + ), # Iron from a heme like in 1GGE + ( + mda.coordinates.PDB.Pair("PLC", "P"), + " P ", + ), # Lipid phosphorus (1EIN) + ), +) 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) -@pytest.mark.parametrize('pdbfile', [PDB_cm, PDB_cm_bz2, PDB_cm_gz, - PDB_mc, PDB_mc_bz2, PDB_mc_gz]) +@pytest.mark.parametrize( + "pdbfile", [PDB_cm, PDB_cm_bz2, PDB_cm_gz, PDB_mc, PDB_mc_bz2, PDB_mc_gz] +) class TestCrystModelOrder(object): """Check offset based reading of pdb files @@ -1163,6 +1354,7 @@ class TestCrystModelOrder(object): # ... # ENDMDL """ + boxsize = [80, 70, 60] position = [10, 20, 30] @@ -1174,7 +1366,8 @@ def test_order(self, pdbfile): u = mda.Universe(pdbfile) for ts, refbox, refpos in zip( - u.trajectory, self.boxsize, self.position): + u.trajectory, self.boxsize, self.position + ): assert_almost_equal(u.dimensions[0], refbox) assert_almost_equal(u.atoms[0].position[0], refpos) @@ -1207,7 +1400,7 @@ def test_write_pdb_zero_atoms(tmpdir): u = make_Universe(trajectory=True) with tmpdir.as_cwd(): - outfile = 'out.pdb' + outfile = "out.pdb" ag = u.atoms[:0] # empty ag @@ -1218,12 +1411,15 @@ 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") atoms = u.select_atoms( - 'resid 1 or resid 10 or resid 100 or resid 1000 or resid 10000') + "resid 1 or resid 10 or resid 100 or resid 1000 or resid 10000" + ) with mda.Writer(outfile, multiframe=True, n_atoms=10) as pdb: # write these two groups of atoms to pdb # Then the n_atoms will not match @@ -1232,20 +1428,25 @@ def test_atom_not_match(tmpdir): reader = mda.coordinates.PDB.PDBReader(outfile) with pytest.raises(ValueError) as excinfo: reader._read_frame(1) - assert 'Inconsistency in file' in str(excinfo.value) + assert "Inconsistency in file" in str(excinfo.value) def test_partially_missing_cryst(): # issue 2252 - raw = open(INC_PDB, 'r').readlines() + raw = open(INC_PDB, "r").readlines() # 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:] - for line in raw] + raw = [ + ( + line + if not line.startswith("CRYST") + else line[:6] + " " * 28 + line[34:] + ) + for line in raw + ] with pytest.warns(UserWarning): - u = mda.Universe(StringIO('\n'.join(raw)), format='PDB') + u = mda.Universe(StringIO("\n".join(raw)), format="PDB") assert len(u.atoms) == 3 assert len(u.trajectory) == 2 @@ -1264,9 +1465,9 @@ def test_write_no_atoms_elements(dummy_universe_without_elements): element_symbols = [ line[76:78].strip() for line in content.splitlines() - if line[:6] == 'ATOM ' + if line[:6] == "ATOM " ] - expectation = ['', '', '', '', ''] + expectation = ["", "", "", "", ""] assert element_symbols == expectation @@ -1277,10 +1478,10 @@ def test_write_atom_elements(dummy_universe_without_elements): See `Issue 2423 `_. """ - elems = ['S', 'O', '', 'C', 'Na'] - expectation = ['S', 'O', '', 'C', 'NA'] + elems = ["S", "O", "", "C", "Na"] + expectation = ["S", "O", "", "C", "NA"] dummy_universe_with_elements = dummy_universe_without_elements - dummy_universe_with_elements.add_TopologyAttr('elements', elems) + dummy_universe_with_elements.add_TopologyAttr("elements", elems) destination = StringIO() with mda.coordinates.PDB.PDBWriter(destination) as writer: writer.write(dummy_universe_without_elements.atoms) @@ -1288,7 +1489,7 @@ def test_write_atom_elements(dummy_universe_without_elements): element_symbols = [ line[76:78].strip() for line in content.splitlines() - if line[:6] == 'ATOM ' + if line[:6] == "ATOM " ] assert element_symbols == expectation @@ -1300,7 +1501,7 @@ def test_elements_roundtrip(tmpdir): u = mda.Universe(CONECT) elements = u.atoms.elements - outfile = os.path.join(str(tmpdir), 'elements.pdb') + outfile = os.path.join(str(tmpdir), "elements.pdb") with mda.coordinates.PDB.PDBWriter(outfile) as writer: writer.write(u.atoms) @@ -1312,14 +1513,16 @@ 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) def test_cryst_meaningless_select(): # issue 2599 u = mda.Universe(PDB_CRYOEM_BOX) - cur_sele = u.select_atoms('around 0.1 (resid 4 and name CA and segid A)') + cur_sele = u.select_atoms("around 0.1 (resid 4 and name CA and segid A)") assert cur_sele.n_atoms == 0 @@ -1329,7 +1532,7 @@ def test_charges_roundtrip(tmpdir): """ u = mda.Universe(PDB_charges) - outfile = os.path.join(str(tmpdir), 'newcharges.pdb') + outfile = os.path.join(str(tmpdir), "newcharges.pdb") with mda.coordinates.PDB.PDBWriter(outfile) as writer: writer.write(u.atoms) @@ -1345,7 +1548,7 @@ def test_charges_not_int(): mda.coordinates.PDB.PDBWriter._format_PDB_charges(arr) -@pytest.mark.parametrize('value', [99, -100]) +@pytest.mark.parametrize("value", [99, -100]) def test_charges_limit(value): # test for raising error when writing charges > 9 arr = np.array([0, 0, 0, value, 1, -1, 0], dtype=int) diff --git a/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py b/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py index 2caf44ecbb..06bc62830b 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py +++ b/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py @@ -51,22 +51,25 @@ def test_chainID(self, universe): assert_equal(sel.n_atoms, 896, "failed to chainID segment B") def test_protein(self, universe): - sel = universe.select_atoms('protein') + sel = universe.select_atoms("protein") assert_equal(sel.n_atoms, 1805, "failed to select protein") - assert_equal(sel.atoms.ix, universe.atoms.ix, - "selected protein is not the same as auto-generated protein segment A+B") + assert_equal( + sel.atoms.ix, + universe.atoms.ix, + "selected protein is not the same as auto-generated protein segment A+B", + ) def test_backbone(self, universe): - sel = universe.select_atoms('backbone') + sel = universe.select_atoms("backbone") assert_equal(sel.n_atoms, 796) def test_neighborhood(self, universe): - '''test KDTree-based distance search around query atoms + """test KDTree-based distance search around query atoms Creates a KDTree of the protein and uses the coordinates of the atoms in the query pdb to create a list of protein residues within 4.0A of the query atoms. - ''' + """ query_universe = mda.Universe(PDBQT_querypdb) # PDB file protein = universe.select_atoms("protein") @@ -76,27 +79,38 @@ 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") def test_frame(self, universe): - assert_equal(universe.trajectory.frame, 0, - "wrong frame number (0-based, should be 0 for single frame readers)") + assert_equal( + universe.trajectory.frame, + 0, + "wrong frame number (0-based, should be 0 for single frame readers)", + ) class TestPDBQTWriter(object): - reqd_attributes = ['names', 'types', 'resids', 'resnames', 'radii', - 'charges'] + reqd_attributes = [ + "names", + "types", + "resids", + "resnames", + "radii", + "charges", + ] @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir) + 'out.pdbqt' + return str(tmpdir) + "out.pdbqt" - @pytest.mark.parametrize('filename', - ['test.pdbqt', 'test.pdbqt.bz2', 'test.pdbqt.gz']) + @pytest.mark.parametrize( + "filename", ["test.pdbqt", "test.pdbqt.bz2", "test.pdbqt.gz"] + ) def test_roundtrip_writing_coords(self, filename, tmpdir): with tmpdir.as_cwd(): @@ -104,17 +118,20 @@ def test_roundtrip_writing_coords(self, filename, tmpdir): u.atoms.write(filename) u2 = mda.Universe(filename) - assert_equal(u2.atoms.positions, u.atoms.positions, - "Round trip does not preserve coordinates") + assert_equal( + u2.atoms.positions, + u.atoms.positions, + "Round trip does not preserve coordinates", + ) def test_roundtrip_formatting(self, outfile): # Compare formatting of first line u = mda.Universe(PDBQT_input) u.atoms.write(outfile) - with open(PDBQT_input, 'r') as inf: + with open(PDBQT_input, "r") as inf: l_ref = inf.readline().strip() - with open(outfile, 'r') as inf: + with open(outfile, "r") as inf: inf.readline() # header inf.readline() # cryst l_new = inf.readline().strip() @@ -127,7 +144,7 @@ def assert_writing_warns(u, outfile): def test_write_no_charges(self, outfile): attrs = self.reqd_attributes - attrs.remove('charges') + attrs.remove("charges") u = make_Universe(attrs, trajectory=True) self.assert_writing_warns(u, outfile) @@ -138,15 +155,15 @@ def test_write_no_charges(self, outfile): def test_write_no_chainids_with_segids(self, outfile): attrs = self.reqd_attributes - attrs.append('segids') + attrs.append("segids") u = make_Universe(attrs, trajectory=True) u.atoms.write(outfile) u2 = mda.Universe(outfile) # Should have used last letter of segid as chainid - assert all(u2.atoms[:25].segids == 'A') - assert all(u2.atoms[25:50].segids == 'B') + assert all(u2.atoms[:25].segids == "A") + assert all(u2.atoms[25:50].segids == "B") def test_get_writer(self, outfile): u = mda.Universe(PDBQT_input) diff --git a/testsuite/MDAnalysisTests/coordinates/test_pqr.py b/testsuite/MDAnalysisTests/coordinates/test_pqr.py index b3a5444724..fc69337ddb 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_pqr.py +++ b/testsuite/MDAnalysisTests/coordinates/test_pqr.py @@ -37,6 +37,7 @@ class TestPQRReader(_SingleFrameReader): __test__ = True + def setUp(self): self.universe = mda.Universe(PQR) # 3 decimals in PDB spec @@ -45,27 +46,39 @@ def setUp(self): def test_total_charge(self): assert_almost_equal( - self.universe.atoms.total_charge(), self.ref_charmm_totalcharge, 3, - "Total charge (in CHARMM) does not match expected value.") + self.universe.atoms.total_charge(), + self.ref_charmm_totalcharge, + 3, + "Total charge (in CHARMM) does not match expected value.", + ) def test_hydrogenCharges(self): - assert_almost_equal(self.universe.select_atoms('name H').charges, - self.ref_charmm_Hcharges, 3, - "Charges for H atoms do not match.") + assert_almost_equal( + self.universe.select_atoms("name H").charges, + self.ref_charmm_Hcharges, + 3, + "Charges for H atoms do not match.", + ) # Note that the whole system gets the sysID 'SYSTEM' for the PQR file (when # read with a PSF it is 's4AKE') def test_ArgCACharges(self): - ag = self.universe.select_atoms('resname ARG and name CA') + ag = self.universe.select_atoms("resname ARG and name CA") assert_almost_equal( - ag.charges, self.ref_charmm_ArgCAcharges, - 3, "Charges for CA atoms in Arg residues do not match.") + ag.charges, + self.ref_charmm_ArgCAcharges, + 3, + "Charges for CA atoms in Arg residues do not match.", + ) def test_ProNCharges(self): - ag = self.universe.select_atoms('resname PRO and name N') + ag = self.universe.select_atoms("resname PRO and name N") assert_almost_equal( - ag.charges, self.ref_charmm_ProNcharges, 3, - "Charges for N atoms in Pro residues do not match.") + ag.charges, + self.ref_charmm_ProNcharges, + 3, + "Charges for N atoms in Pro residues do not match.", + ) def test_dimensions(self): # Issue #3327 - dimensions should always be set to None @@ -80,87 +93,116 @@ 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) u2 = mda.Universe(filename) - assert_equal(universe.atoms.positions, - u2.atoms.positions) + assert_equal(universe.atoms.positions, u2.atoms.positions) def test_writer_noChainID(self, universe, tmpdir): - outfile = str(tmpdir.join('pqr-test.pqr')) + outfile = str(tmpdir.join("pqr-test.pqr")) - assert_equal(universe.segments.segids[0], 'SYSTEM') + assert_equal(universe.segments.segids[0], "SYSTEM") universe.atoms.write(outfile) u = mda.Universe(outfile) - assert_equal(u.segments.segids[0], 'SYSTEM') - assert_almost_equal(u.atoms.positions, - universe.atoms.positions, self.prec, - err_msg="Writing PQR file with PQRWriter does " - "not reproduce original coordinates") - assert_almost_equal(u.atoms.charges, universe.atoms.charges, - self.prec, err_msg="Writing PQR file with " - "PQRWriter does not reproduce original charges") - assert_almost_equal(u.atoms.radii, universe.atoms.radii, - self.prec, err_msg="Writing PQR file with " - "PQRWriter does not reproduce original radii") + assert_equal(u.segments.segids[0], "SYSTEM") + assert_almost_equal( + u.atoms.positions, + universe.atoms.positions, + self.prec, + err_msg="Writing PQR file with PQRWriter does " + "not reproduce original coordinates", + ) + assert_almost_equal( + u.atoms.charges, + universe.atoms.charges, + self.prec, + err_msg="Writing PQR file with " + "PQRWriter does not reproduce original charges", + ) + assert_almost_equal( + u.atoms.radii, + universe.atoms.radii, + self.prec, + err_msg="Writing PQR file with " + "PQRWriter does not reproduce original radii", + ) # 363 TODO: # Not sure if this should be a segid or chainID? # Topology system now allows for both of these def test_write_withChainID(self, universe, tmpdir): - outfile = str(tmpdir.join('pqr-test.pqr')) + outfile = str(tmpdir.join("pqr-test.pqr")) - universe.segments.segids = 'A' - assert_equal(universe.segments.segids[0], 'A') # sanity check + universe.segments.segids = "A" + assert_equal(universe.segments.segids[0], "A") # sanity check universe.atoms.write(outfile) u = mda.Universe(outfile) - assert_equal(u.segments.segids[0], 'A') - assert_almost_equal(u.atoms.positions, - universe.atoms.positions, self.prec, - err_msg="Writing PQR file with PQRWriter does " - "not reproduce original coordinates") - assert_almost_equal(u.atoms.charges, universe.atoms.charges, - self.prec, err_msg="Writing PQR file with " - "PQRWriter does not reproduce original charges") - assert_almost_equal(u.atoms.radii, universe.atoms.radii, - self.prec, err_msg="Writing PQR file with " - "PQRWriter does not reproduce original radii") + assert_equal(u.segments.segids[0], "A") + assert_almost_equal( + u.atoms.positions, + universe.atoms.positions, + self.prec, + err_msg="Writing PQR file with PQRWriter does " + "not reproduce original coordinates", + ) + assert_almost_equal( + u.atoms.charges, + universe.atoms.charges, + self.prec, + err_msg="Writing PQR file with " + "PQRWriter does not reproduce original charges", + ) + assert_almost_equal( + u.atoms.radii, + universe.atoms.radii, + self.prec, + err_msg="Writing PQR file with " + "PQRWriter does not reproduce original radii", + ) def test_timestep_not_modified_by_writer(self, universe, tmpdir): - outfile = str(tmpdir.join('pqr-test.pqr')) + outfile = str(tmpdir.join("pqr-test.pqr")) ts = universe.trajectory.ts x = ts.positions.copy() universe.atoms.write(outfile) - assert_equal(ts.positions, x, - err_msg="Positions in Timestep were modified by writer.") + assert_equal( + ts.positions, + x, + err_msg="Positions in Timestep were modified by writer.", + ) def test_total_charge(self, universe, tmpdir): - outfile = str(tmpdir.join('pqr-test.pqr')) + outfile = str(tmpdir.join("pqr-test.pqr")) universe.atoms.write(outfile) u = mda.Universe(outfile) assert_almost_equal( - u.atoms.total_charge(), self.ref_charmm_totalcharge, 3, - "Total charge (in CHARMM) does not match expected value.") + u.atoms.total_charge(), + self.ref_charmm_totalcharge, + 3, + "Total charge (in CHARMM) does not match expected value.", + ) + class TestPQRWriterMissingAttrs(object): # pqr requires names, resids, resnames, segids, radii, charges @staticmethod @pytest.fixture def reqd_attributes(): - return ['names', 'resids', 'resnames', 'radii', 'charges'] + return ["names", "resids", "resnames", "radii", "charges"] @staticmethod @pytest.fixture def outfile(tmpdir): - return str(tmpdir.join('pqr-writer-test.pqr')) + return str(tmpdir.join("pqr-writer-test.pqr")) def test_no_names_writing(self, reqd_attributes, outfile): attrs = reqd_attributes - attrs.remove('names') + attrs.remove("names") u = make_Universe(attrs, trajectory=True) with pytest.warns(UserWarning): @@ -168,11 +210,11 @@ def test_no_names_writing(self, reqd_attributes, outfile): u2 = mda.Universe(outfile) - assert all(u2.atoms.names == 'X') + assert all(u2.atoms.names == "X") def test_no_resnames_writing(self, reqd_attributes, outfile): attrs = reqd_attributes - attrs.remove('resnames') + attrs.remove("resnames") u = make_Universe(attrs, trajectory=True) with pytest.warns(UserWarning): @@ -180,11 +222,11 @@ def test_no_resnames_writing(self, reqd_attributes, outfile): u2 = mda.Universe(outfile) - assert all(u2.residues.resnames == 'UNK') + assert all(u2.residues.resnames == "UNK") def test_no_radii_writing(self, reqd_attributes, outfile): attrs = reqd_attributes - attrs.remove('radii') + attrs.remove("radii") u = make_Universe(attrs, trajectory=True) with pytest.warns(UserWarning): @@ -196,7 +238,7 @@ def test_no_radii_writing(self, reqd_attributes, outfile): def test_no_charges_writing(self, reqd_attributes, outfile): attrs = reqd_attributes - attrs.remove('charges') + attrs.remove("charges") u = make_Universe(attrs, trajectory=True) with pytest.warns(UserWarning): diff --git a/testsuite/MDAnalysisTests/coordinates/test_reader_api.py b/testsuite/MDAnalysisTests/coordinates/test_reader_api.py index c2062ab995..4ae5c0f5c6 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_reader_api.py +++ b/testsuite/MDAnalysisTests/coordinates/test_reader_api.py @@ -20,23 +20,24 @@ # MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # -import numpy as np from collections import OrderedDict + +import numpy as np +import pytest from MDAnalysis.coordinates.base import ( - Timestep, + ReaderBase, SingleFrameReaderBase, - ReaderBase + Timestep, ) -from numpy.testing import assert_equal, assert_allclose +from numpy.testing import assert_allclose, assert_equal -import pytest """ Isolate the API definitions of Readers independent of implementations """ class AmazingMultiFrameReader(ReaderBase): - format = 'AmazingMulti' + format = "AmazingMulti" def __init__(self, filename, **kwargs): self.filename = filename @@ -71,7 +72,7 @@ def _reopen(self): class AmazingReader(SingleFrameReaderBase): - format = 'Amazing' + format = "Amazing" # have to hack this in to get the base class to "work" def _read_first_frame(self): @@ -86,7 +87,7 @@ class _TestReader(object): @pytest.fixture() def reader(self): - return self.readerclass('test.txt') + return self.readerclass("test.txt") @pytest.fixture() def ts(self, reader): @@ -94,10 +95,17 @@ def ts(self, reader): def test_required_attributes(self, reader): """Test that Reader has the required attributes""" - for attr in ['filename', 'n_atoms', 'n_frames', 'ts', - 'units', 'format']: - assert_equal(hasattr(reader, attr), True, - "Missing attr: {0}".format(attr)) + for attr in [ + "filename", + "n_atoms", + "n_frames", + "ts", + "units", + "format", + ]: + assert_equal( + hasattr(reader, attr), True, "Missing attr: {0}".format(attr) + ) def test_iter(self, reader): l = [ts for ts in reader] @@ -105,7 +113,7 @@ def test_iter(self, reader): assert_equal(len(l), self.n_frames) def test_close(self): - sfr = self.readerclass('text.txt') + sfr = self.readerclass("text.txt") ret = sfr.close() # Check that method works? @@ -118,7 +126,7 @@ def test_rewind(self, reader): assert_equal(reader.ts.frame, 0) def test_context(self): - with self.readerclass('text.txt') as sfr: + with self.readerclass("text.txt") as sfr: l = sfr.ts.frame assert_equal(l, 0) @@ -133,16 +141,17 @@ def test_raises_StopIteration(self, reader): with pytest.raises(StopIteration): next(reader) - @pytest.mark.parametrize('order', ['turnip', 'abc']) + @pytest.mark.parametrize("order", ["turnip", "abc"]) def test_timeseries_raises_unknown_order_key(self, reader, order): with pytest.raises(ValueError, match="Unrecognized order key"): reader.timeseries(order=order) - @pytest.mark.parametrize('order', ['faac', 'affc', 'afcc', '']) + @pytest.mark.parametrize("order", ["faac", "affc", "afcc", ""]) def test_timeseries_raises_incorrect_order_key(self, reader, order): with pytest.raises(ValueError, match="Repeated or missing keys"): reader.timeseries(order=order) + class _Multi(_TestReader): n_frames = 10 n_atoms = 10 @@ -154,34 +163,37 @@ class TestMultiFrameReader(_Multi): __test__ = True - @pytest.mark.parametrize('start, stop, step', [ - (None, None, None), # blank slice - (None, 5, None), # set end point - (2, None, None), # set start point - (2, 5, None), # start & end - (None, None, 2), # set skip - (None, None, -1), # backwards skip - (None, -1, -1), - (10, 0, -1), - (0, 10, 1), - (0, 10, 2), - (None, 20, None), # end beyond real end - (None, 20, 2), # with skip - (0, 5, 2), - (5, None, -1), - (None, 5, -1), - (100, 10, 1), - (-10, None, 1), - (100, None, -1), # beyond real end - (100, 5, -20), - (5, 1, 1), # Stop less than start - (1, 5, -1), # Stop less than start - (-100, None, None), - (100, None, None), # Outside of range of trajectory - (-2, 10, -2), - (0, 0, 1), # empty - (10, 1, 2), # empty - ]) + @pytest.mark.parametrize( + "start, stop, step", + [ + (None, None, None), # blank slice + (None, 5, None), # set end point + (2, None, None), # set start point + (2, 5, None), # start & end + (None, None, 2), # set skip + (None, None, -1), # backwards skip + (None, -1, -1), + (10, 0, -1), + (0, 10, 1), + (0, 10, 2), + (None, 20, None), # end beyond real end + (None, 20, 2), # with skip + (0, 5, 2), + (5, None, -1), + (None, 5, -1), + (100, 10, 1), + (-10, None, 1), + (100, None, -1), # beyond real end + (100, 5, -20), + (5, 1, 1), # Stop less than start + (1, 5, -1), # Stop less than start + (-100, None, None), + (100, None, None), # Outside of range of trajectory + (-2, 10, -2), + (0, 0, 1), # empty + (10, 1, 2), # empty + ], + ) def test_slice(self, start, stop, step, reader): """Compare the slice applied to trajectory, to slice of list""" res = [ts.frame for ts in reader[start:stop:step]] @@ -203,16 +215,30 @@ def sl(): with pytest.raises(TypeError): sl() - @pytest.mark.parametrize('slice_cls', [list, np.array]) - @pytest.mark.parametrize('sl', [ - [0, 1, 4, 5], - [5, 1, 6, 2, 7, 3, 8], - [0, 1, 1, 1, 0, 0, 2, 3, 4], - [True, False, True, False, True, False, True, False, True, False], - [True, True, False, False, True, True, False, True, False, True], - [True, True, True, True, True, True, True, True, True, True], - [False, False, False, False, False, False, False, False, False, False], - ]) + @pytest.mark.parametrize("slice_cls", [list, np.array]) + @pytest.mark.parametrize( + "sl", + [ + [0, 1, 4, 5], + [5, 1, 6, 2, 7, 3, 8], + [0, 1, 1, 1, 0, 0, 2, 3, 4], + [True, False, True, False, True, False, True, False, True, False], + [True, True, False, False, True, True, False, True, False, True], + [True, True, True, True, True, True, True, True, True, True], + [ + False, + False, + False, + False, + False, + False, + False, + False, + False, + False, + ], + ], + ) def test_getitem(self, slice_cls, sl, reader): sl = slice_cls(sl) res = [ts.frame for ts in reader[sl]] @@ -222,23 +248,26 @@ def test_getitem(self, slice_cls, sl, reader): assert_equal(res, ref) - @pytest.mark.parametrize('sl', [ - [0, 1, 2, 3], # ordered list of indices without duplicates - [1, 3, 4, 2, 9], # disordered list of indices without duplicates - [0, 1, 1, 2, 2, 2], # ordered list with duplicates - [-1, -2, 3, -1, 0], # disordered list with duplicates - [True, ] * 10, - [False, ] * 10, - [True, False, ] * 5, - slice(None, None, None), - slice(0, 10, 1), - slice(None, None, -1), - slice(10, 0, -1), - slice(2, 7, 2), - slice(7, 2, -2), - slice(7, 2, 1), # empty - slice(0, 0, 1), # empty - ]) + @pytest.mark.parametrize( + "sl", + [ + [0, 1, 2, 3], # ordered list of indices without duplicates + [1, 3, 4, 2, 9], # disordered list of indices without duplicates + [0, 1, 1, 2, 2, 2], # ordered list with duplicates + [-1, -2, 3, -1, 0], # disordered list with duplicates + [True] * 10, + [False] * 10, + [True, False] * 5, + slice(None, None, None), + slice(0, 10, 1), + slice(None, None, -1), + slice(10, 0, -1), + slice(2, 7, 2), + slice(7, 2, -2), + slice(7, 2, 1), # empty + slice(0, 0, 1), # empty + ], + ) def test_getitem_len(self, sl, reader): traj_iterable = reader[sl] if not isinstance(sl, slice): @@ -246,31 +275,37 @@ def test_getitem_len(self, sl, reader): ref = self.reference[sl] assert len(traj_iterable) == len(ref) - @pytest.mark.parametrize('iter_type', (list, np.array)) + @pytest.mark.parametrize("iter_type", (list, np.array)) def test_getitem_len_empty(self, reader, iter_type): # Indexing a numpy array with an empty array tends to break. traj_iterable = reader[iter_type([])] assert len(traj_iterable) == 0 # All the sl1 slice must be 5 frames long so that the sl2 can be a mask - @pytest.mark.parametrize('sl1', [ - [0, 1, 2, 3, 4], - [1, 1, 1, 1, 1], - [True, False, ] * 5, - slice(None, None, 2), - slice(None, None, -2), - ]) - @pytest.mark.parametrize('sl2', [ - [0, -1, 2], - [-1,-1, -1], - [True, False, True, True, False], - np.array([True, False, True, True, False]), - slice(None, None, None), - slice(None, 3, None), - slice(4, 0, -1), - slice(None, None, -1), - slice(None, None, 2), - ]) + @pytest.mark.parametrize( + "sl1", + [ + [0, 1, 2, 3, 4], + [1, 1, 1, 1, 1], + [True, False] * 5, + slice(None, None, 2), + slice(None, None, -2), + ], + ) + @pytest.mark.parametrize( + "sl2", + [ + [0, -1, 2], + [-1, -1, -1], + [True, False, True, True, False], + np.array([True, False, True, True, False]), + slice(None, None, None), + slice(None, 3, None), + slice(4, 0, -1), + slice(None, None, -1), + slice(None, None, 2), + ], + ) def test_double_getitem(self, sl1, sl2, reader): traj_iterable = reader[sl1][sl2] # Old versions of numpy do not behave the same when indexing with a @@ -285,15 +320,18 @@ def test_double_getitem(self, sl1, sl2, reader): assert_equal(res, ref) assert len(traj_iterable) == len(ref) - @pytest.mark.parametrize('sl1', [ - [0, 1, 2, 3, 4], - [1, 1, 1, 1, 1], - [True, False, ] * 5, - slice(None, None, 2), - slice(None, None, -2), - slice(None, None, None), - ]) - @pytest.mark.parametrize('idx2', [0, 2, 4, -1, -2, -4]) + @pytest.mark.parametrize( + "sl1", + [ + [0, 1, 2, 3, 4], + [1, 1, 1, 1, 1], + [True, False] * 5, + slice(None, None, 2), + slice(None, None, -2), + slice(None, None, None), + ], + ) + @pytest.mark.parametrize("idx2", [0, 2, 4, -1, -2, -4]) def test_double_getitem_int(self, sl1, idx2, reader): ts = reader[sl1][idx2] # Old versions of numpy do not behave the same when indexing with a @@ -305,7 +343,7 @@ def test_double_getitem_int(self, sl1, idx2, reader): def test_list_TE(self, reader): def sl(): - return list(reader[[0, 'a', 5, 6]]) + return list(reader[[0, "a", 5, 6]]) with pytest.raises(TypeError): sl() @@ -317,14 +355,17 @@ def sl(): with pytest.raises(TypeError): sl() - @pytest.mark.parametrize('sl1', [ - [0, 1, 2, 3, 4], - [1, 1, 1, 1, 1], - [True, False, ] * 5, - slice(None, None, 2), - slice(None, None, -2), - ]) - @pytest.mark.parametrize('idx2', [5, -6]) + @pytest.mark.parametrize( + "sl1", + [ + [0, 1, 2, 3, 4], + [1, 1, 1, 1, 1], + [True, False] * 5, + slice(None, None, 2), + slice(None, None, -2), + ], + ) + @pytest.mark.parametrize("idx2", [5, -6]) def test_getitem_IE(self, sl1, idx2, reader): partial_reader = reader[sl1] with pytest.raises(IndexError): @@ -339,6 +380,7 @@ class _Single(_TestReader): class TestSingleFrameReader(_Single): __test__ = True + def test_next(self, reader): with pytest.raises(StopIteration): reader.next() diff --git a/testsuite/MDAnalysisTests/coordinates/test_timestep_api.py b/testsuite/MDAnalysisTests/coordinates/test_timestep_api.py index a12934199d..1b2bc468b3 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_timestep_api.py +++ b/testsuite/MDAnalysisTests/coordinates/test_timestep_api.py @@ -28,18 +28,45 @@ """ import itertools import numpy as np -from numpy.testing import assert_equal, assert_allclose, assert_array_almost_equal +from numpy.testing import ( + assert_equal, + assert_allclose, + assert_array_almost_equal, +) from MDAnalysis.lib.mdamath import triclinic_vectors import MDAnalysis as mda -from MDAnalysisTests.datafiles import (PSF, XYZ_five, INPCRD, DCD, DLP_CONFIG, - DLP_HISTORY, DMS, GMS_ASYMOPT, GRO, XTC, - TRR, LAMMPSdata, LAMMPSdata2, - LAMMPSdcd2, mol2_molecules, PDB_small, - PDBQT_input, PQR, PRM, TRJ, PRMncdf, - NCDF, TRZ_psf, TRZ) - -from MDAnalysisTests.coordinates.base import assert_timestep_equal, assert_timestep_almost_equal +from MDAnalysisTests.datafiles import ( + PSF, + XYZ_five, + INPCRD, + DCD, + DLP_CONFIG, + DLP_HISTORY, + DMS, + GMS_ASYMOPT, + GRO, + XTC, + TRR, + LAMMPSdata, + LAMMPSdata2, + LAMMPSdcd2, + mol2_molecules, + PDB_small, + PDBQT_input, + PQR, + PRM, + TRJ, + PRMncdf, + NCDF, + TRZ_psf, + TRZ, +) + +from MDAnalysisTests.coordinates.base import ( + assert_timestep_equal, + assert_timestep_almost_equal, +) from MDAnalysis.coordinates.timestep import Timestep import pytest @@ -52,6 +79,7 @@ class TestTimestep(object): These test the Timestep independent of the Reader which it comes into contact with. Failures here are the Timesteps fault. """ + # define the class made in test Timestep = Timestep name = "base" # for error messages only @@ -63,9 +91,9 @@ class TestTimestep(object): # If you can set box, what the underlying unitcell should be # if dimensions are: - newbox = np.array([10., 11., 12., 90., 90., 90.]) - unitcell = np.array([10., 11., 12., 90., 90., 90.]) - ref_volume = 1320. # what the volume is after setting newbox + newbox = np.array([10.0, 11.0, 12.0, 90.0, 90.0, 90.0]) + unitcell = np.array([10.0, 11.0, 12.0, 90.0, 90.0, 90.0]) + ref_volume = 1320.0 # what the volume is after setting newbox uni_args = None @pytest.fixture() @@ -87,7 +115,6 @@ def test_getitem_neg_IE(self, ts): with pytest.raises(IndexError): ts.__getitem__(-(self.size + 1)) - def test_getitem_pos_IE(self, ts): with pytest.raises(IndexError): ts.__getitem__((self.size + 1)) @@ -107,7 +134,7 @@ def test_getitem_ndarray(self, ts): def test_getitem_TE(self, ts): with pytest.raises(TypeError): - ts.__getitem__('string') + ts.__getitem__("string") def test_len(self, ts): assert_equal(len(ts), self.size) @@ -121,16 +148,15 @@ def test_repr(self, ts): assert_equal(type(repr(ts)), str) def test_repr_with_box(self, ts): - assert("with unit cell dimensions" in repr(ts)) + assert "with unit cell dimensions" in repr(ts) def test_repr_no_box(self, ts): ts.dimensions = None - assert("with unit cell dimensions" not in repr(ts)) + assert "with unit cell dimensions" not in repr(ts) def test_default_dtype_npf32(self, ts): assert_equal(ts.dtype, np.float32) - # Dimensions has 2 possible cases # Timestep doesn't do dimensions, # returns None for .dimension and 0 for .volume @@ -138,7 +164,7 @@ def test_default_dtype_npf32(self, ts): def test_dimensions(self, ts): assert_allclose(ts.dimensions, self.newbox) - @pytest.mark.parametrize('dtype', (int, np.float32, np.float64)) + @pytest.mark.parametrize("dtype", (int, np.float32, np.float64)) def test_dimensions_set_box(self, ts, dtype): ts.dimensions = self.newbox.astype(dtype) assert ts.dimensions.dtype == np.float32 @@ -149,21 +175,22 @@ 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) ts.triclinic_dimensions = ref_vec assert_equal(ts.dimensions, self.newbox) - def test_set_dimensions_None(self,ts): + def test_set_dimensions_None(self, ts): ts.dimensions = None - assert(not ts._unitcell.any()) + assert not ts._unitcell.any() - def test_set_triclinic_dimensions_None(self,ts): + def test_set_triclinic_dimensions_None(self, ts): ts.triclinic_dimensions = None - assert(not ts._unitcell.any()) + assert not ts._unitcell.any() def test_coordinate_getter_shortcuts(self, ts): """testing that reading _x, _y, and _z works as expected @@ -174,7 +201,7 @@ def test_coordinate_getter_shortcuts(self, ts): def test_coordinate_setter_shortcuts(self, ts): # Check that _x _y and _z are read only - for coordinate in ('_x', '_y', '_z'): + for coordinate in ("_x", "_y", "_z"): random_positions = np.arange(self.size).astype(np.float32) with pytest.raises(AttributeError): setattr(ts, coordinate, random_positions) @@ -186,22 +213,22 @@ def test_n_atoms(self, ts): def test_n_atoms_readonly(self, ts): with pytest.raises(AttributeError): - ts.__setattr__('n_atoms', 20) + ts.__setattr__("n_atoms", 20) def test_n_atoms_presence(self, ts): - assert_equal(hasattr(ts, 'n_atoms'), True) + assert_equal(hasattr(ts, "n_atoms"), True) def test_unitcell_presence(self, ts): - assert_equal(hasattr(ts, 'dimensions'), True) + assert_equal(hasattr(ts, "dimensions"), True) def test_data_presence(self, ts): - assert_equal(hasattr(ts, 'data'), True) + assert_equal(hasattr(ts, "data"), True) assert_equal(isinstance(ts.data, dict), True) def test_allocate_velocities(self, ts): assert_equal(ts.has_velocities, False) with pytest.raises(mda.NoDataError): - getattr(ts, 'velocities') + getattr(ts, "velocities") ts.has_velocities = True assert_equal(ts.has_velocities, True) @@ -210,7 +237,7 @@ def test_allocate_velocities(self, ts): def test_allocate_forces(self, ts): assert_equal(ts.has_forces, False) with pytest.raises(mda.NoDataError): - getattr(ts, 'forces') + getattr(ts, "forces") ts.has_forces = True assert_equal(ts.has_forces, True) @@ -224,7 +251,7 @@ def test_velocities_remove(self): ts.has_velocities = False assert_equal(ts.has_velocities, False) with pytest.raises(mda.NoDataError): - getattr(ts, 'velocities') + getattr(ts, "velocities") def test_forces_remove(self): ts = self.Timestep(10, forces=True) @@ -234,7 +261,7 @@ def test_forces_remove(self): ts.has_forces = False assert_equal(ts.has_forces, False) with pytest.raises(mda.NoDataError): - getattr(ts, 'forces') + getattr(ts, "forces") def test_check_ts(self): with pytest.raises(ValueError): @@ -249,9 +276,9 @@ def _from_coords(self, p, v, f): return ts - @pytest.mark.parametrize('p, v, f', filter(any, - itertools.product([True, False], - repeat=3))) + @pytest.mark.parametrize( + "p, v, f", filter(any, itertools.product([True, False], repeat=3)) + ) def test_from_coordinates(self, p, v, f): ts = self._from_coords(p, v, f) @@ -259,17 +286,17 @@ def test_from_coordinates(self, p, v, f): assert_array_almost_equal(ts.positions, self.refpos) else: with pytest.raises(mda.NoDataError): - getattr(ts, 'positions') + getattr(ts, "positions") if v: assert_array_almost_equal(ts.velocities, self.refvel) else: with pytest.raises(mda.NoDataError): - getattr(ts, 'velocities') + getattr(ts, "velocities") if f: assert_array_almost_equal(ts.forces, self.reffor) else: with pytest.raises(mda.NoDataError): - getattr(ts, 'forces') + getattr(ts, "forces") def test_from_coordinates_mismatch(self): velo = self.refvel[:2] @@ -286,29 +313,29 @@ def test_supply_dt(self): # Check that this gets stored in data properly ts = self.Timestep(20, dt=0.04) - assert_equal(ts.data['dt'], 0.04) + assert_equal(ts.data["dt"], 0.04) assert_equal(ts.dt, 0.04) def test_redefine_dt(self): ts = self.Timestep(20, dt=0.04) - assert_equal(ts.data['dt'], 0.04) + assert_equal(ts.data["dt"], 0.04) assert_equal(ts.dt, 0.04) ts.dt = refdt = 0.46 - assert_equal(ts.data['dt'], refdt) + assert_equal(ts.data["dt"], refdt) assert_equal(ts.dt, refdt) def test_delete_dt(self): ts = self.Timestep(20, dt=0.04) - assert_equal(ts.data['dt'], 0.04) + assert_equal(ts.data["dt"], 0.04) assert_equal(ts.dt, 0.04) del ts.dt - assert_equal('dt' in ts.data, False) + assert_equal("dt" in ts.data, False) assert_equal(ts.dt, 1.0) # default value def test_supply_time_offset(self): ts = self.Timestep(20, time_offset=100.0) - assert_equal(ts.data['time_offset'], 100.0) + assert_equal(ts.data["time_offset"], 100.0) def test_time(self): ts = self.Timestep(20) @@ -379,8 +406,9 @@ 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 @@ -389,8 +417,9 @@ 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 @@ -398,8 +427,7 @@ def _check_copy(self, name, ref_ts): for d in ref_ts.data: assert d in ts2.data if isinstance(ref_ts.data[d], np.ndarray): - assert_array_almost_equal( - ref_ts.data[d], ts2.data[d]) + assert_array_almost_equal(ref_ts.data[d], ts2.data[d]) else: assert ref_ts.data[d] == ts2.data[d] @@ -433,10 +461,27 @@ def _check_copy_slice_slice(self, name, ts): self._check_slice(ts, ts2, sl) def _check_npint_slice(self, name, ts): - for integers in [np.byte, np.short, np.intc, np.int_, np.longlong, - np.intp, np.int8, np.int16, np.int32, np.int64, - np.ubyte, np.ushort, np.uintc, np.ulonglong, - np.uintp, np.uint8, np.uint16, np.uint32, np.uint64]: + for integers in [ + np.byte, + np.short, + np.intc, + np.int_, + np.longlong, + np.intp, + np.int8, + np.int16, + np.int32, + np.int64, + np.ubyte, + np.ushort, + np.uintc, + np.ulonglong, + np.uintp, + np.uint8, + np.uint16, + np.uint32, + np.uint64, + ]: sl = slice(1, 2, 1) ts2 = ts.copy_slice(slice(integers(1), integers(2), integers(1))) self._check_slice(ts, ts2, sl) @@ -449,13 +494,16 @@ def _check_slice(self, ts1, ts2, sl): if ts1.has_forces: assert_array_almost_equal(ts1.forces[sl], ts2.forces) - @pytest.mark.parametrize('func', [ - _check_copy, - _check_independent, - _check_copy_slice_indices, - _check_copy_slice_slice, - _check_npint_slice - ]) + @pytest.mark.parametrize( + "func", + [ + _check_copy, + _check_independent, + _check_copy_slice_indices, + _check_copy_slice_slice, + _check_npint_slice, + ], + ) def test_copy(self, func, ts): if self.uni_args is None: return @@ -463,24 +511,28 @@ 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) - @pytest.mark.parametrize('func', [ - _check_copy, - _check_independent, - _check_copy_slice_indices, - _check_copy_slice_slice, - _check_npint_slice - ]) + @pytest.mark.parametrize( + "func", + [ + _check_copy, + _check_independent, + _check_copy_slice_indices, + _check_copy_slice_slice, + _check_npint_slice, + ], + ) def test_copy_slice(self, func, some_ts): func(self, self.name, some_ts) def test_bad_slice(self, some_ts): - sl = ['this', 'is', 'silly'] + sl = ["this", "is", "silly"] with pytest.raises(TypeError): some_ts.copy_slice(sl) @@ -494,18 +546,12 @@ def _get_pos(self): # Get generic reference positions return np.arange(30).reshape(10, 3) * 1.234 - @pytest.mark.parametrize('p, v, f', filter(any, - itertools.product([True, False], - repeat=3))) + @pytest.mark.parametrize( + "p, v, f", filter(any, itertools.product([True, False], repeat=3)) + ) def test_check_equal(self, p, v, f): - ts1 = self.Timestep(self.size, - positions=p, - velocities=v, - forces=f) - ts2 = self.Timestep(self.size, - positions=p, - velocities=v, - forces=f) + ts1 = self.Timestep(self.size, positions=p, velocities=v, forces=f) + ts2 = self.Timestep(self.size, positions=p, velocities=v, forces=f) if p: ts1.positions = self.refpos.copy() ts2.positions = self.refpos.copy() @@ -622,12 +668,12 @@ def test_check_wrong_forces_equality(self): assert ts1 != ts2 assert ts2 != ts1 - @pytest.mark.parametrize('dim1', [None, [2., 2., 2., 90., 90., 90.]]) + @pytest.mark.parametrize("dim1", [None, [2.0, 2.0, 2.0, 90.0, 90.0, 90.0]]) def test_dims_mismatch_inequality(self, dim1): ts1 = self.Timestep(self.size) ts1.dimensions = dim1 ts2 = self.Timestep(self.size) - ts2.dimensions = [1., 1., 1., 90., 90., 90.] + ts2.dimensions = [1.0, 1.0, 1.0, 90.0, 90.0, 90.0] assert ts1 != ts2 assert ts2 != ts1 @@ -637,6 +683,7 @@ def test_dims_mismatch_inequality(self, dim1): # These tests are all included in BaseReaderTest # Once Readers use that TestClass, delete this one + class TestBaseTimestepInterface(object): """Test the Timesteps created by Readers @@ -647,32 +694,41 @@ class TestBaseTimestepInterface(object): See Issue #250 for discussion """ - @pytest.fixture(params=( - (XYZ_five, INPCRD, None, None), - (PSF, DCD, None, None), - (DLP_CONFIG, None, 'CONFIG', None), - (DLP_HISTORY, None, 'HISTORY', None), - (DMS, None, None, None), - (GRO, None, None, None), - (XYZ_five, INPCRD, None, None), - (LAMMPSdata, None, None, None), - (mol2_molecules, None, None, None), - (PDB_small, None, None, None), - (PQR, None, None, None), - (PDBQT_input, None, None, None), - (PRM, TRJ, None, None), - (GRO, XTC, None, None), - (TRZ_psf, TRZ, None, None), - (GRO, TRR, None, None), - (GMS_ASYMOPT, GMS_ASYMOPT, 'GMS', 'GMS'), - (LAMMPSdata2, LAMMPSdcd2, 'LAMMPS', 'DATA'), - (PRMncdf, NCDF, None, None), - )) + + @pytest.fixture( + params=( + (XYZ_five, INPCRD, None, None), + (PSF, DCD, None, None), + (DLP_CONFIG, None, "CONFIG", None), + (DLP_HISTORY, None, "HISTORY", None), + (DMS, None, None, None), + (GRO, None, None, None), + (XYZ_five, INPCRD, None, None), + (LAMMPSdata, None, None, None), + (mol2_molecules, None, None, None), + (PDB_small, None, None, None), + (PQR, None, None, None), + (PDBQT_input, None, None, None), + (PRM, TRJ, None, None), + (GRO, XTC, None, None), + (TRZ_psf, TRZ, None, None), + (GRO, TRR, None, None), + (GMS_ASYMOPT, GMS_ASYMOPT, "GMS", "GMS"), + (LAMMPSdata2, LAMMPSdcd2, "LAMMPS", "DATA"), + (PRMncdf, NCDF, None, None), + ) + ) 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, trajectory, format=trajectory_format, - topology_format=topology_format) + return mda.Universe( + topology, + trajectory, + format=trajectory_format, + topology_format=topology_format, + ) if trajectory is not None: return mda.Universe(topology, trajectory) @@ -686,15 +742,18 @@ def test_dt(self, universe): assert_equal(universe.trajectory.dt, universe.trajectory.ts.dt) -@pytest.mark.parametrize('uni', [ - [(PSF, DCD), {}], # base Timestep - [(DLP_CONFIG,), {'format': 'CONFIG'}], # DLPoly - [(DMS,), {}], # DMS - [(GRO,), {}], # GRO - [(np.zeros((1, 30, 3)),), {}], # memory - [(PRM, TRJ), {}], # TRJ - [(TRZ_psf, TRZ), {}], # TRZ -]) +@pytest.mark.parametrize( + "uni", + [ + [(PSF, DCD), {}], # base Timestep + [(DLP_CONFIG,), {"format": "CONFIG"}], # DLPoly + [(DMS,), {}], # DMS + [(GRO,), {}], # GRO + [(np.zeros((1, 30, 3)),), {}], # memory + [(PRM, TRJ), {}], # TRJ + [(TRZ_psf, TRZ), {}], # TRZ + ], +) def test_atomgroup_dims_access(uni): uni_args, uni_kwargs = uni # check that AtomGroup.dimensions always returns a copy diff --git a/testsuite/MDAnalysisTests/coordinates/test_tng.py b/testsuite/MDAnalysisTests/coordinates/test_tng.py index c9ea9b8678..8eaa64d5ec 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_tng.py +++ b/testsuite/MDAnalysisTests/coordinates/test_tng.py @@ -241,7 +241,9 @@ 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): @@ -253,7 +255,9 @@ 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) @@ -289,7 +293,9 @@ 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 @@ -315,21 +321,29 @@ 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 @@ -341,7 +355,9 @@ 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 @@ -396,8 +412,12 @@ 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 @@ -406,8 +426,12 @@ 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 430eb42237..f01f6c7ed9 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_trc.py +++ b/testsuite/MDAnalysisTests/coordinates/test_trc.py @@ -50,7 +50,9 @@ 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 @@ -91,13 +93,17 @@ 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), ( - "The atom positions are not populated" - ) + assert np.any( + TRC_U.atoms.positions != 0 + ), "The atom positions are not populated" def test_random_access(self, TRC_U): TRC_U.trajectory[0] @@ -132,7 +138,8 @@ def test_periodic(self, TRC_U): def test_trc_dimensions(self, TRC_U): ts = TRC_U.trajectory[1] assert_allclose( - ts.dimensions, [30.54416298, 30.54416298, 30.54416298, 90.0, 90.0, 90.0] + ts.dimensions, + [30.54416298, 30.54416298, 30.54416298, 90.0, 90.0, 90.0], ) def test_open_twice(self, TRC_U): @@ -149,7 +156,8 @@ def TRC_U(self): def test_trc_dimensions(self, TRC_U): ts = TRC_U.trajectory[1] assert_allclose( - ts.dimensions, [3.054416298, 3.054416298, 3.054416298, 90.0, 90.0, 90.0] + ts.dimensions, + [3.054416298, 3.054416298, 3.054416298, 90.0, 90.0, 90.0], ) @@ -197,8 +205,14 @@ 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 @@ -235,7 +249,9 @@ 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) @@ -274,11 +290,15 @@ 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 1ba1271f5f..65c1e62dba 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_trj.py +++ b/testsuite/MDAnalysisTests/coordinates/test_trj.py @@ -23,70 +23,91 @@ import numpy as np import pytest -from numpy.testing import ( - assert_equal, - assert_almost_equal -) +from numpy.testing import assert_equal, assert_almost_equal import MDAnalysis as mda from MDAnalysisTests.coordinates.reference import RefACHE, RefCappedAla -from MDAnalysisTests.datafiles import (PRM, TRJ, TRJ_bz2, PRMpbc, TRJpbc_bz2) +from MDAnalysisTests.datafiles import PRM, TRJ, TRJ_bz2, PRMpbc, TRJpbc_bz2 class _TRJReaderTest(object): - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def universe(self): return mda.Universe(self.topology_file, self.trajectory_file) def test_load_prm(self, universe): - assert_equal(len(universe.atoms), self.ref_n_atoms, - "load Universe from PRM and TRJ") + assert_equal( + len(universe.atoms), + self.ref_n_atoms, + "load Universe from PRM and TRJ", + ) def test_n_atoms(self, universe): - assert_equal(universe.trajectory.n_atoms, self.ref_n_atoms, - "wrong number of atoms") + assert_equal( + universe.trajectory.n_atoms, + self.ref_n_atoms, + "wrong number of atoms", + ) def test_n_frames(self, universe): - assert_equal(universe.trajectory.n_frames, self.ref_n_frames, - "wrong number of frames in xyz") + assert_equal( + universe.trajectory.n_frames, + self.ref_n_frames, + "wrong number of frames in xyz", + ) def test_periodic(self, universe): assert_equal(universe.trajectory.periodic, self.ref_periodic) def test_amber_proteinselection(self, universe): - protein = universe.select_atoms('protein') - assert_equal(protein.n_atoms, self.ref_proteinatoms, - "error in protein selection (HIS or termini?)") + protein = universe.select_atoms("protein") + assert_equal( + protein.n_atoms, + self.ref_proteinatoms, + "error in protein selection (HIS or termini?)", + ) 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]) - 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") + protein = universe.select_atoms("protein") + 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", + ) 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)) + assert_equal( + universe.trajectory.ts.frame, + 0, + "initial frame is not 0 but {0}".format( + universe.trajectory.ts.frame + ), + ) def test_starts_with_first_frame(self, universe): """Test that coordinate arrays are filled as soon as the trajectory has been opened.""" - assert np.any(universe.atoms.positions > 0), "Reader does not " \ - "populate positions right away." + assert np.any(universe.atoms.positions > 0), ( + "Reader does not " "populate positions right away." + ) 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), "Reader does not " \ - "populate positions after rewinding." + assert np.any(universe.atoms.positions > 0), ( + "Reader does not " "populate positions after rewinding." + ) def test_full_slice(self, universe): trj_iter = universe.trajectory[:] @@ -135,4 +156,4 @@ class TestBzippedTRJReaderPBC(_TRJReaderTest, RefCappedAla): def test_trj_no_natoms(): with pytest.raises(ValueError): - mda.coordinates.TRJ.TRJReader('somefile.txt') + mda.coordinates.TRJ.TRJReader("somefile.txt") diff --git a/testsuite/MDAnalysisTests/coordinates/test_trz.py b/testsuite/MDAnalysisTests/coordinates/test_trz.py index ea455bb8c7..8e42bc644f 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_trz.py +++ b/testsuite/MDAnalysisTests/coordinates/test_trz.py @@ -24,15 +24,11 @@ import MDAnalysis as mda import os -from numpy.testing import ( - assert_equal, - assert_almost_equal, - assert_allclose -) +from numpy.testing import assert_equal, assert_almost_equal, assert_allclose import numpy as np from MDAnalysisTests.coordinates.reference import RefTRZ -from MDAnalysisTests.datafiles import (TRZ_psf, TRZ, two_water_gro) +from MDAnalysisTests.datafiles import TRZ_psf, TRZ, two_water_gro def test_deprecated_trz_reader(): @@ -49,7 +45,7 @@ def test_deprecated_trz_writer(tmpdir): with pytest.warns(DeprecationWarning, match=wmsg): with tmpdir.as_cwd(): - with mda.coordinates.TRZ.TRZWriter('test.trz', len(u.atoms)) as W: + with mda.coordinates.TRZ.TRZWriter("test.trz", len(u.atoms)) as W: W.write(u) @@ -64,14 +60,16 @@ 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 @@ -80,8 +78,11 @@ def test_rewind_trz(self, universe): assert_equal(universe.trajectory.ts.frame, 0, "rewinding to frame 1") def test_n_frames(self, universe): - assert_equal(universe.trajectory.n_frames, self.ref_n_frames, - "wrong number of frames in trz") + assert_equal( + universe.trajectory.n_frames, + self.ref_n_frames, + "wrong number of frames in trz", + ) def test_seeking(self, universe): universe.trajectory[3] @@ -93,58 +94,79 @@ def test_seeking(self, universe): assert_equal(universe.trajectory.ts.frame, 4, "loading frame 4") universe.trajectory[3] - assert_almost_equal(universe.atoms[0:3].positions, orig, - self.prec) + assert_almost_equal(universe.atoms[0:3].positions, orig, self.prec) universe.trajectory[0] assert_equal(universe.trajectory.ts.frame, 0, "loading frame 0") universe.trajectory[3] - assert_almost_equal(universe.atoms[0:3].positions, orig, - self.prec) + assert_almost_equal(universe.atoms[0:3].positions, orig, self.prec) def test_volume(self, universe): # Lower precision here because errors seem to accumulate and # throw this off (is rounded value**3) - assert_almost_equal(universe.trajectory.ts.volume, self.ref_volume, 1, - "wrong volume for trz") + assert_almost_equal( + universe.trajectory.ts.volume, + self.ref_volume, + 1, + "wrong volume for trz", + ) def test_unitcell(self, universe): - assert_almost_equal(universe.trajectory.ts.dimensions, - self.ref_dimensions, self.prec, - "wrong dimensions for trz") + assert_almost_equal( + universe.trajectory.ts.dimensions, + self.ref_dimensions, + self.prec, + "wrong dimensions for trz", + ) def test_coordinates(self, universe): fortytwo = universe.atoms[41] # 41 because is 0 based - assert_almost_equal(fortytwo.position, self.ref_coordinates, self.prec, - "wrong coordinates in trz") + assert_almost_equal( + fortytwo.position, + self.ref_coordinates, + self.prec, + "wrong coordinates in trz", + ) def test_velocities(self, universe): - fortytwo = universe.select_atoms('bynum 42') - assert_almost_equal(fortytwo.velocities, self.ref_velocities, - self.prec, "wrong velocities in trz") + fortytwo = universe.select_atoms("bynum 42") + assert_almost_equal( + fortytwo.velocities, + self.ref_velocities, + self.prec, + "wrong velocities in trz", + ) def test_delta(self, universe): - assert_almost_equal(universe.trajectory.delta, self.ref_delta, - self.prec, - "wrong time delta in trz") + assert_almost_equal( + universe.trajectory.delta, + self.ref_delta, + self.prec, + "wrong time delta in trz", + ) def test_time(self, universe): - assert_almost_equal(universe.trajectory.time, self.ref_time, self.prec, - "wrong time value in trz") + assert_almost_equal( + universe.trajectory.time, + self.ref_time, + self.prec, + "wrong time value in trz", + ) 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') + self.outfile = os.path.join(str(tmpdir), "test-trz-writer.trz") with universe.trajectory.Writer(self.outfile) as W: assert_equal(isinstance(W, mda.coordinates.TRZ.TRZWriter), True) assert_equal(W.n_atoms, universe.trajectory.n_atoms) def test_get_writer_2(self, universe, tmpdir): - self.outfile = os.path.join(str(tmpdir), 'test-trz-writer-1.trz') + self.outfile = os.path.join(str(tmpdir), "test-trz-writer-1.trz") with universe.trajectory.Writer(self.outfile, n_atoms=100) as W: assert_equal(isinstance(W, mda.coordinates.TRZ.TRZWriter), True) assert_equal(W.n_atoms, 100) @@ -154,7 +176,7 @@ def test_get_wrong_n_atoms(self): mda.Universe(TRZ, n_atoms=8080) def test_read_zero_box(self, tmpdir): - outfile = str(tmpdir.join('/test-trz-writer.trz')) + outfile = str(tmpdir.join("/test-trz-writer.trz")) u = mda.Universe.empty(10, trajectory=True) u.dimensions = None @@ -171,7 +193,7 @@ def test_read_zero_box(self, tmpdir): class TestTRZWriter(RefTRZ): prec = 3 writer = mda.coordinates.TRZ.TRZWriter - title_to_write = 'Test title TRZ' + title_to_write = "Test title TRZ" @pytest.fixture() def universe(self): @@ -179,7 +201,7 @@ def universe(self): @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir.join('/test-trz-writer.trz')) + return str(tmpdir.join("/test-trz-writer.trz")) def test_write_trajectory(self, universe, outfile): t = universe.trajectory @@ -193,32 +215,44 @@ def _copy_traj(self, writer, universe, outfile): uw = mda.Universe(TRZ_psf, outfile) - assert_equal(uw.trajectory.title, self.title_to_write, - "Title mismatch between original and written files.") - - for orig_ts, written_ts in zip(universe.trajectory, - uw.trajectory): - assert_almost_equal(orig_ts._pos, written_ts._pos, self.prec, - err_msg="Coordinate mismatch between " - "orig and written at frame %d" % - orig_ts.frame) - assert_almost_equal(orig_ts._velocities, - written_ts._velocities, self.prec, - err_msg="Coordinate mismatch between " - "orig and written at frame %d" % - orig_ts.frame) - assert_almost_equal(orig_ts._unitcell, written_ts._unitcell, - self.prec, err_msg="Unitcell mismatch " - "between orig and written at frame %d" % - orig_ts.frame) + assert_equal( + uw.trajectory.title, + self.title_to_write, + "Title mismatch between original and written files.", + ) + + for orig_ts, written_ts in zip(universe.trajectory, uw.trajectory): + assert_almost_equal( + orig_ts._pos, + written_ts._pos, + self.prec, + err_msg="Coordinate mismatch between " + "orig and written at frame %d" % orig_ts.frame, + ) + assert_almost_equal( + orig_ts._velocities, + written_ts._velocities, + self.prec, + err_msg="Coordinate mismatch between " + "orig and written at frame %d" % orig_ts.frame, + ) + assert_almost_equal( + orig_ts._unitcell, + written_ts._unitcell, + self.prec, + err_msg="Unitcell mismatch " + "between orig and written at frame %d" % orig_ts.frame, + ) for att in orig_ts.data: - assert_almost_equal(orig_ts.data[att], - written_ts.data[att], self.prec, - err_msg="TS equal failed for {0!s}".format( - att)) + assert_almost_equal( + orig_ts.data[att], + written_ts.data[att], + self.prec, + err_msg="TS equal failed for {0!s}".format(att), + ) def test_long_title(self, outfile): - title = '*' * 81 + title = "*" * 81 with pytest.raises(ValueError): self.writer(outfile, self.ref_n_atoms, title=title) @@ -226,8 +260,9 @@ 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) @@ -240,7 +275,7 @@ def u(self): @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir.join('/trz-writer-2.trz')) + return str(tmpdir.join("/trz-writer-2.trz")) def test_writer_trz_from_other(self, u, outfile): with mda.coordinates.TRZ.TRZWriter(outfile, len(u.atoms)) as W: @@ -256,7 +291,7 @@ def test_no_dt_warning(self, u, outfile): u2 = mda.Universe(two_water_gro, outfile) - wmsg = ('Reader has no dt information, set to 1.0 ps') + wmsg = "Reader has no dt information, set to 1.0 ps" with pytest.warns(UserWarning, match=wmsg): assert_allclose(u2.trajectory.dt, 1.0) @@ -270,6 +305,7 @@ class TestWrite_Partial_Timestep(object): just checks that Writer is receiving this information properly. """ + prec = 3 @pytest.fixture() @@ -277,15 +313,17 @@ def universe(self): return mda.Universe(TRZ_psf, TRZ) def test_write_trajectory(self, universe, tmpdir): - ag = universe.select_atoms('name N') - outfile = str(tmpdir.join('/partial-write-test.pdb')) + ag = universe.select_atoms("name N") + outfile = str(tmpdir.join("/partial-write-test.pdb")) writer = mda.Writer(outfile, n_atoms=len(ag)) writer.write(ag) writer.close() u_ag = mda.Universe(outfile) - assert_almost_equal(ag.positions, - u_ag.atoms.positions, - self.prec, - err_msg="Writing AtomGroup timestep failed.") + assert_almost_equal( + ag.positions, + u_ag.atoms.positions, + self.prec, + err_msg="Writing AtomGroup timestep failed.", + ) diff --git a/testsuite/MDAnalysisTests/coordinates/test_txyz.py b/testsuite/MDAnalysisTests/coordinates/test_txyz.py index fda7e62ba8..66cd38067e 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_txyz.py +++ b/testsuite/MDAnalysisTests/coordinates/test_txyz.py @@ -44,20 +44,23 @@ 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): @@ -69,10 +72,11 @@ def test_arcpbc_traj_length(ARC_PBC_U): def test_pbc_boxsize(ARC_PBC_U): - ref_dimensions=[[ 38.860761, 38.860761, 38.860761, 90.000000, 90.000000, 90.000000], - [ 39.860761, 39.860761, 39.860761, 90.000000, 90.000000, 90.000000], - [ 40.860761, 40.860761, 40.860761, 90.000000, 90.000000, 90.000000]] + ref_dimensions = [ + [38.860761, 38.860761, 38.860761, 90.000000, 90.000000, 90.000000], + [39.860761, 39.860761, 39.860761, 90.000000, 90.000000, 90.000000], + [40.860761, 40.860761, 40.860761, 90.000000, 90.000000, 90.000000], + ] for ref_box, ts in zip(ref_dimensions, ARC_PBC_U.trajectory): assert_almost_equal(ref_box, ts.dimensions, decimal=5) - diff --git a/testsuite/MDAnalysisTests/coordinates/test_windows.py b/testsuite/MDAnalysisTests/coordinates/test_windows.py index 723ce5e689..86194e1e4b 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_windows.py +++ b/testsuite/MDAnalysisTests/coordinates/test_windows.py @@ -49,26 +49,36 @@ class TestWinLammpsDump(TestLammpsDumpReader): @pytest.fixture def u(self): - return mda.Universe(WIN_LAMMPSDUMP, format='LAMMPSDUMP') + return mda.Universe(WIN_LAMMPSDUMP, format="LAMMPSDUMP") class TestWinPDB(object): @staticmethod - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def multiverse(): return mda.Universe(WIN_PDB_multiframe, guess_bonds=True) def test_n_frames(self, multiverse): - assert_equal(multiverse.trajectory.n_frames, 24, - "Wrong number of frames read from PDB muliple model file") + assert_equal( + multiverse.trajectory.n_frames, + 24, + "Wrong number of frames read from PDB muliple model file", + ) + def test_rewind(self, multiverse): u = multiverse u.trajectory[11] - assert_equal(u.trajectory.ts.frame, 11, - "Failed to forward to 11th frame (frame index 11)") + assert_equal( + u.trajectory.ts.frame, + 11, + "Failed to forward to 11th frame (frame index 11)", + ) u.trajectory.rewind() - assert_equal(u.trajectory.ts.frame, 0, - "Failed to rewind to 0th frame (frame index 0)") + assert_equal( + u.trajectory.ts.frame, + 0, + "Failed to rewind to 0th frame (frame index 0)", + ) def test_iteration(self, multiverse): u = multiverse @@ -80,19 +90,23 @@ def test_iteration(self, multiverse): for ts in u.trajectory: frames.append(ts) assert_equal( - len(frames), u.trajectory.n_frames, + len(frames), + u.trajectory.n_frames, "iterated number of frames %d is not the expected number %d; " - "trajectory iterator fails to rewind" % - (len(frames), u.trajectory.n_frames)) + "trajectory iterator fails to rewind" + % (len(frames), u.trajectory.n_frames), + ) def test_slice_iteration(self, multiverse): u = multiverse frames = [] for ts in u.trajectory[4:-2:4]: frames.append(ts.frame) - assert_equal(np.array(frames), - np.arange(u.trajectory.n_frames)[4:-2:4], - err_msg="slicing did not produce the expected frames") + assert_equal( + np.array(frames), + np.arange(u.trajectory.n_frames)[4:-2:4], + err_msg="slicing did not produce the expected frames", + ) class TestWinDLPolyHistory(TestDLPolyHistory): @@ -113,11 +127,13 @@ def test_n_frames(self, WIN_ARC_U): assert len(WIN_ARC_U.trajectory) == 2 def test_positions(self, WIN_ARC_U): - assert_almost_equal(WIN_ARC_U.atoms.positions[0], - [-6.553398, -1.854369, 0.000000]) + assert_almost_equal( + WIN_ARC_U.atoms.positions[0], [-6.553398, -1.854369, 0.000000] + ) def test_positions_2(self, WIN_ARC_U): WIN_ARC_U.trajectory[1] - assert_almost_equal(WIN_ARC_U.atoms.positions[0], - [-0.231579, -0.350841, -0.037475]) + assert_almost_equal( + WIN_ARC_U.atoms.positions[0], [-0.231579, -0.350841, -0.037475] + ) diff --git a/testsuite/MDAnalysisTests/coordinates/test_writer_api.py b/testsuite/MDAnalysisTests/coordinates/test_writer_api.py index 54d364fb75..4c3ac08cb5 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_writer_api.py +++ b/testsuite/MDAnalysisTests/coordinates/test_writer_api.py @@ -27,9 +27,11 @@ # 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()), - key=lambda x: x.__name__) +writers = sorted( + set(mda._MULTIFRAME_WRITERS.values()) + | set(mda._SINGLEFRAME_WRITERS.values()), + key=lambda x: x.__name__, +) known_ts_haters = [ mda.coordinates.MOL2.MOL2Writer, mda.coordinates.PDB.PDBWriter, @@ -41,7 +43,7 @@ ] -@pytest.mark.parametrize('writer', writers) +@pytest.mark.parametrize("writer", writers) def test_ts_error(writer, tmpdir): u = mda.Universe.empty(10, trajectory=True) @@ -49,16 +51,21 @@ def test_ts_error(writer, tmpdir): # chemfiles Writer exists but doesn't work without chemfiles if not mda.coordinates.chemfiles.check_chemfiles_version(): pytest.skip("Chemfiles not available") - fn = str(tmpdir.join('out.xtc')) + fn = str(tmpdir.join("out.xtc")) 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: + elif ( + writer == mda.coordinates.H5MD.H5MDWriter + and not mda.coordinates.H5MD.HAS_H5PY + ): pytest.skip("skipping H5MDWriter test because h5py is not installed") else: - fn = str(tmpdir.join('out.traj')) + fn = str(tmpdir.join("out.traj")) - if (writer == mda.coordinates.PDB.PDBWriter or - writer == mda.coordinates.PDB.MultiPDBWriter): + if ( + writer == mda.coordinates.PDB.PDBWriter + or writer == mda.coordinates.PDB.MultiPDBWriter + ): errmsg = "PDBWriter cannot write Timestep objects directly" else: errmsg = "neither an AtomGroup or Universe" @@ -68,7 +75,7 @@ def test_ts_error(writer, tmpdir): w.write(u.trajectory.ts) -@pytest.mark.parametrize('writer', writers) +@pytest.mark.parametrize("writer", writers) def test_write_with_atomgroup(writer, tmpdir): u = mda.Universe.empty(10, trajectory=True) @@ -76,25 +83,28 @@ def test_write_with_atomgroup(writer, tmpdir): # chemfiles Writer exists but doesn't work without chemfiles if not mda.coordinates.chemfiles.check_chemfiles_version(): pytest.skip("Chemfiles not available") - fn = str(tmpdir.join('out.xtc')) + fn = str(tmpdir.join("out.xtc")) elif writer == mda.coordinates.MOL2.MOL2Writer: pytest.skip("MOL2 only writes MOL2 back out") 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: + elif ( + writer == mda.coordinates.H5MD.H5MDWriter + and not mda.coordinates.H5MD.HAS_H5PY + ): pytest.skip("skipping H5MDWriter test because h5py is not installed") else: - fn = str(tmpdir.join('out.traj')) + fn = str(tmpdir.join("out.traj")) # H5MDWriter raises ValueError if the trajectory has no units and # convert_units is True - convert_units = (writer != mda.coordinates.H5MD.H5MDWriter) + convert_units = writer != mda.coordinates.H5MD.H5MDWriter with writer(fn, n_atoms=u.atoms.n_atoms, convert_units=convert_units) as w: w.write(u.atoms) -@pytest.mark.parametrize('writer', writers) +@pytest.mark.parametrize("writer", writers) def test_write_with_universe(writer, tmpdir): u = mda.Universe.empty(10, trajectory=True) @@ -102,19 +112,22 @@ def test_write_with_universe(writer, tmpdir): # chemfiles Writer exists but doesn't work without chemfiles if not mda.coordinates.chemfiles.check_chemfiles_version(): pytest.skip("Chemfiles not available") - fn = str(tmpdir.join('out.xtc')) + fn = str(tmpdir.join("out.xtc")) elif writer == mda.coordinates.MOL2.MOL2Writer: pytest.skip("MOL2 only writes MOL2 back out") 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: + elif ( + writer == mda.coordinates.H5MD.H5MDWriter + and not mda.coordinates.H5MD.HAS_H5PY + ): pytest.skip("skipping H5MDWriter test because h5py is not installed") else: - fn = str(tmpdir.join('out.traj')) + fn = str(tmpdir.join("out.traj")) # H5MDWriter raises ValueError if the trajectory has no units and # convert_units is True - convert_units = (writer != mda.coordinates.H5MD.H5MDWriter) + convert_units = writer != mda.coordinates.H5MD.H5MDWriter with writer(fn, n_atoms=u.atoms.n_atoms, convert_units=convert_units) as w: w.write(u.atoms) diff --git a/testsuite/MDAnalysisTests/coordinates/test_writer_registration.py b/testsuite/MDAnalysisTests/coordinates/test_writer_registration.py index e5fdf19744..616bae0ef6 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_writer_registration.py +++ b/testsuite/MDAnalysisTests/coordinates/test_writer_registration.py @@ -29,7 +29,7 @@ class TestWriterCreation(object): class MagicWriter(WriterBase): # this writer does the 'magic' format - format = 'MAGIC' + format = "MAGIC" def __init__(self, filename, n_atoms=None): self.filename = filename @@ -38,22 +38,24 @@ def __init__(self, filename, n_atoms=None): class MultiMagicWriter(MagicWriter): # this writer does the 'magic' and 'magic2' formats # but *only* supports multiframe writing. - format = ['MAGIC', 'MAGIC2'] + format = ["MAGIC", "MAGIC2"] multiframe = True singleframe = False def test_default_multiframe(self): - assert isinstance(mda.Writer('this.magic'), self.MultiMagicWriter) + assert isinstance(mda.Writer("this.magic"), self.MultiMagicWriter) 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 - assert isinstance(mda.Writer('that.magic2'), self.MultiMagicWriter) + assert isinstance(mda.Writer("that.magic2"), self.MultiMagicWriter) def test_singleframe_magic2(self): # this should fail, there isn't a singleframe writer for magic2 with pytest.raises(TypeError): - mda.Writer('that.magic2', multiframe=False) + mda.Writer("that.magic2", multiframe=False) diff --git a/testsuite/MDAnalysisTests/coordinates/test_xdr.py b/testsuite/MDAnalysisTests/coordinates/test_xdr.py index efb15d7825..4a356eed04 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_xdr.py +++ b/testsuite/MDAnalysisTests/coordinates/test_xdr.py @@ -30,17 +30,31 @@ from pathlib import Path import numpy as np -from numpy.testing import (assert_equal, - assert_almost_equal, - assert_allclose) +from numpy.testing import assert_equal, assert_almost_equal, assert_allclose from MDAnalysisTests import make_Universe from MDAnalysisTests.datafiles import ( - PDB_sub_dry, PDB_sub_sol, TRR_sub_sol, TRR, XTC, GRO, PDB, CRD, PRMncdf, - NCDF, XTC_sub_sol, COORDINATES_XTC, COORDINATES_TOPOLOGY, COORDINATES_TRR) -from MDAnalysisTests.coordinates.base import (MultiframeReaderTest, - BaseReference, BaseWriterTest, - assert_timestep_almost_equal) + PDB_sub_dry, + PDB_sub_sol, + TRR_sub_sol, + TRR, + XTC, + GRO, + PDB, + CRD, + PRMncdf, + NCDF, + XTC_sub_sol, + COORDINATES_XTC, + COORDINATES_TOPOLOGY, + COORDINATES_TRR, +) +from MDAnalysisTests.coordinates.base import ( + MultiframeReaderTest, + BaseReference, + BaseWriterTest, + assert_timestep_almost_equal, +) import MDAnalysis as mda from MDAnalysis.coordinates.base import Timestep @@ -48,11 +62,14 @@ from MDAnalysisTests.util import get_userid -@pytest.mark.parametrize("filename,kwargs,reference", [ - ("foo.xtc", {}, ".foo.xtc_offsets.npz"), - ("foo.xtc", {"ending": "npz"}, ".foo.xtc_offsets.npz"), - ("bar.0001.trr", {"ending": "npzzzz"}, ".bar.0001.trr_offsets.npzzzz"), -]) +@pytest.mark.parametrize( + "filename,kwargs,reference", + [ + ("foo.xtc", {}, ".foo.xtc_offsets.npz"), + ("foo.xtc", {"ending": "npz"}, ".foo.xtc_offsets.npz"), + ("bar.0001.trr", {"ending": "npzzzz"}, ".bar.0001.trr_offsets.npzzzz"), + ], +) def test_offsets_filename(filename, kwargs, reference): fn = XDR.offsets_filename(filename, **kwargs) assert fn == reference @@ -93,13 +110,14 @@ class _GromacsReader(object): # This base class assumes same lengths and dt for XTC and TRR test cases! filename = None ref_unitcell = np.array( - [80.017, 80.017, 80.017, 60., 60., 90.], dtype=np.float32) + [80.017, 80.017, 80.017, 60.0, 60.0, 90.0], dtype=np.float32 + ) # computed with Gromacs: 362.26999999999998 nm**3 * 1000 A**3/nm**3 ref_volume = 362270.0 prec = 3 - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def universe(self): return mda.Universe(GRO, self.filename, convert_units=True) @@ -119,8 +137,9 @@ 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]] @@ -132,22 +151,23 @@ def test_reverse_xdrtrj(self, universe): def test_coordinates(self, universe): ca_nm = np.array( - [[6.043369675, 7.385184479, 1.381425762]], dtype=np.float32) + [[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() universe.trajectory.next() universe.trajectory.next() assert_equal(universe.coord.frame, 2, "failed to step to frame 3") - ca = universe.select_atoms('name CA and resid 122') + ca = universe.select_atoms("name CA and resid 122") # low precision match (2 decimals in A, 3 in nm) because the above are # the trr coords assert_almost_equal( ca.positions, ca_Angstrom, 2, - err_msg="coords of Ca of resid 122 do not " - "match for frame 3") + err_msg="coords of Ca of resid 122 do not " "match for frame 3", + ) def test_unitcell(self, universe): """Test that xtc/trr unitcell is read correctly (Issue 34)""" @@ -157,7 +177,8 @@ def test_unitcell(self, universe): uc, self.ref_unitcell, self.prec, - err_msg="unit cell dimensions (rhombic dodecahedron)") + err_msg="unit cell dimensions (rhombic dodecahedron)", + ) def test_volume(self, universe): # need to reduce precision for test (nm**3 <--> A**3) @@ -167,11 +188,13 @@ def test_volume(self, universe): vol, self.ref_volume, 0, - err_msg="unit cell volume (rhombic dodecahedron)") + err_msg="unit cell volume (rhombic dodecahedron)", + ) def test_dt(self, universe): assert_almost_equal( - universe.trajectory.dt, 100.0, 4, err_msg="wrong timestep dt") + universe.trajectory.dt, 100.0, 4, err_msg="wrong timestep dt" + ) def test_totaltime(self, universe): # test_totaltime(): need to reduce precision because dt is only precise @@ -181,7 +204,8 @@ def test_totaltime(self, universe): universe.trajectory.totaltime, 900.0, 3, - err_msg="wrong total length of trajectory") + err_msg="wrong total length of trajectory", + ) def test_frame(self, universe): universe.trajectory[4] # index is 0-based and frames are 0-based @@ -190,11 +214,12 @@ def test_frame(self, universe): def test_time(self, universe): universe.trajectory[4] assert_almost_equal( - universe.trajectory.time, 400.0, 3, err_msg="wrong time of frame") + universe.trajectory.time, 400.0, 3, err_msg="wrong time of frame" + ) def test_get_Writer(self, universe, tmpdir): ext = os.path.splitext(self.filename)[1] - outfile = str(tmpdir.join('xdr-reader-test' + ext)) + outfile = str(tmpdir.join("xdr-reader-test" + ext)) with universe.trajectory.Writer(outfile) as W: assert_equal(universe.trajectory.format, W.format) assert_equal(universe.atoms.n_atoms, W.n_atoms) @@ -202,7 +227,7 @@ def test_get_Writer(self, universe, tmpdir): def test_Writer(self, tmpdir): universe = mda.Universe(GRO, self.filename, convert_units=True) ext = os.path.splitext(self.filename)[1] - outfile = str(tmpdir.join('/xdr-reader-test' + ext)) + outfile = str(tmpdir.join("/xdr-reader-test" + ext)) with universe.trajectory.Writer(outfile) as W: W.write(universe.atoms) universe.trajectory.next() @@ -213,8 +238,9 @@ def test_Writer(self, tmpdir): 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 + ) def test_EOFraisesStopIteration(self, universe): def go_beyond_EOF(): @@ -227,11 +253,12 @@ def go_beyond_EOF(): def test_read_next_timestep_ts_no_positions(self, universe): # primarily tests branching on ts.has_positions in _read_next_timestep ts = universe.trajectory[0] - ts.has_positions=False + ts.has_positions = False ts_passed_in = universe.trajectory._read_next_timestep(ts=ts).copy() universe.trajectory.rewind() ts_returned = universe.trajectory._read_next_timestep(ts=None).copy() - assert(ts_passed_in == ts_returned) + assert ts_passed_in == ts_returned + class TestXTCReader(_GromacsReader): filename = XTC @@ -250,11 +277,13 @@ def test_with_statement(self): assert_equal( N, 10, - err_msg="with_statement: XTCReader reads wrong number of frames") + err_msg="with_statement: XTCReader reads wrong number of frames", + ) assert_equal( frames, np.arange(0, N), - err_msg="with_statement: XTCReader does not read all frames") + err_msg="with_statement: XTCReader does not read all frames", + ) class TestTRRReader(_GromacsReader): @@ -266,9 +295,12 @@ def test_velocities(self, universe): # v[47675]={-7.86469e-01, 1.57479e+00, 2.79722e-01} # v[47676]={ 2.70593e-08, 1.08052e-06, 6.97028e-07} v_native = np.array( - [[-7.86469e-01, 1.57479e+00, 2.79722e-01], - [2.70593e-08, 1.08052e-06, 6.97028e-07]], - dtype=np.float32) + [ + [-7.86469e-01, 1.57479e00, 2.79722e-01], + [2.70593e-08, 1.08052e-06, 6.97028e-07], + ], + dtype=np.float32, + ) # velocities in the MDA base unit A/ps (needed for True) v_base = v_native * 10.0 @@ -280,22 +312,26 @@ def test_velocities(self, universe): v_base, self.prec, err_msg="ts._velocities for indices 47675,47676 do not " - "match known values") + "match known values", + ) assert_almost_equal( universe.atoms.velocities[[47675, 47676]], v_base, self.prec, err_msg="velocities for indices 47675,47676 do not " - "match known values") + "match known values", + ) for index, v_known in zip([47675, 47676], v_base): assert_almost_equal( universe.atoms[index].velocity, v_known, self.prec, - err_msg="atom[{0:d}].velocity does not match known values". - format(index)) + err_msg="atom[{0:d}].velocity does not match known values".format( + index + ), + ) class _XDRNoConversion(object): @@ -308,13 +344,15 @@ 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) + [[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") - ca = universe.select_atoms('name CA and resid 122') + 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! assert_almost_equal( @@ -323,7 +361,8 @@ def test_coordinates(self, universe): 3, err_msg="native coords of Ca of resid 122 " "do not match for frame 3 with " - "convert_units=False") + "convert_units=False", + ) class TestXTCNoConversion(_XDRNoConversion): @@ -337,11 +376,11 @@ class TestTRRNoConversion(_XDRNoConversion): class _GromacsWriter(object): infilename = None # XTC or TRR Writers = { - '.trr': mda.coordinates.TRR.TRRWriter, - '.xtc': mda.coordinates.XTC.XTCWriter, + ".trr": mda.coordinates.TRR.TRRWriter, + ".xtc": mda.coordinates.XTC.XTCWriter, } - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def universe(self): return mda.Universe(GRO, self.infilename) @@ -353,11 +392,13 @@ def Writer(self): @pytest.fixture() def outfile(self, tmpdir): ext = os.path.splitext(self.infilename)[1] - return str(tmpdir.join('xdr-writer-test' + ext)) + return str(tmpdir.join("xdr-writer-test" + ext)) 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) @@ -371,8 +412,9 @@ 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): trj = universe.trajectory @@ -390,9 +432,11 @@ def test_timestep_not_modified_by_writer(self, universe, Writer, outfile): assert_equal( ts._pos, x, - err_msg="Positions in Timestep were modified by writer.") + err_msg="Positions in Timestep were modified by writer.", + ) assert_equal( - ts.time, time, err_msg="Time in Timestep was modified by writer.") + ts.time, time, err_msg="Time in Timestep was modified by writer." + ) class TestXTCWriter(_GromacsWriter): @@ -405,7 +449,9 @@ 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) @@ -419,13 +465,16 @@ 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. @@ -447,10 +496,11 @@ def test_gaps(self, universe, Writer, outfile): err_msg="coordinates mismatch " "between original and written " "trajectory at frame {} (orig) " - "vs {} (written)".format(orig_ts.frame, written_ts.frame)) + "vs {} (written)".format(orig_ts.frame, written_ts.frame), + ) else: with pytest.raises(mda.NoDataError): - getattr(written_ts, 'positions') + getattr(written_ts, "positions") if ts.frame % 2 != 0: assert_almost_equal( @@ -460,23 +510,26 @@ def test_gaps(self, universe, Writer, outfile): err_msg="velocities mismatch " "between original and written " "trajectory at frame {} (orig) " - "vs {} (written)".format(orig_ts.frame, written_ts.frame)) + "vs {} (written)".format(orig_ts.frame, written_ts.frame), + ) else: with pytest.raises(mda.NoDataError): - getattr(written_ts, 'velocities') + getattr(written_ts, "velocities") def test_data_preservation(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) uw = mda.Universe(GRO, outfile) - assert np.isclose(ts.data['time'], 0.0) - assert ts.data['step'] == 0 - assert np.isclose(ts.data['lambda'], 0.0) - assert np.isclose(ts.data['dt'], 100.0) + assert np.isclose(ts.data["time"], 0.0) + assert ts.data["step"] == 0 + assert np.isclose(ts.data["lambda"], 0.0) + assert np.isclose(ts.data["dt"], 100.0) # check that the data are identical for each time step for orig_ts, written_ts in zip(universe.trajectory, uw.trajectory): @@ -487,21 +540,23 @@ def test_data_preservation(self, universe, Writer, outfile): for k in orig_ts.data: assert k in written_ts.data - err_msg = ('mismatch between ' - 'original and written trajectory at ' - f'frame {orig_ts.frame} vs {written_ts.frame}') + err_msg = ( + "mismatch between " + "original and written trajectory at " + f"frame {orig_ts.frame} vs {written_ts.frame}" + ) # 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): Writers = { - '.trr': mda.coordinates.TRR.TRRWriter, - '.xtc': mda.coordinates.XTC.XTCWriter, + ".trr": mda.coordinates.TRR.TRRWriter, + ".xtc": mda.coordinates.XTC.XTCWriter, } ext = None # set to '.xtc' or '.trr' prec = 3 @@ -512,7 +567,7 @@ def Writer(self): @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir.join('/xdr-writer-issue101' + self.ext)) + return str(tmpdir.join("/xdr-writer-issue101" + self.ext)) def test_single_frame_GRO(self, Writer, outfile): self._single_frame(GRO, Writer, outfile) @@ -528,13 +583,17 @@ def _single_frame(self, filename, Writer, outfile): with Writer(outfile, u.atoms.n_atoms) as W: W.write(u.atoms) w = mda.Universe(filename, outfile) - assert_equal(w.trajectory.n_frames, 1, - "single frame trajectory has wrong number of frames") + assert_equal( + w.trajectory.n_frames, + 1, + "single frame trajectory has wrong number of frames", + ) assert_almost_equal( w.atoms.positions, u.atoms.positions, self.prec, - err_msg="coordinates do not match for {0!r}".format(filename)) + err_msg="coordinates do not match for {0!r}".format(filename), + ) class TestXTCWriterSingleFrame(_GromacsWriterIssue101): @@ -548,6 +607,7 @@ class TestTRRWriterSingleFrame(_GromacsWriterIssue101): class _GromacsWriterIssue117(object): """Issue 117: Cannot write XTC or TRR from AMBER NCDF""" + ext = None prec = 5 @@ -558,7 +618,7 @@ def universe(self): @pytest.mark.filterwarnings("ignore: ATOMIC_NUMBER record not found") def test_write_trajectory(self, universe, tmpdir): """Test writing Gromacs trajectories from AMBER NCDF (Issue 117)""" - outfile = str(tmpdir.join('xdr-writer-issue117' + self.ext)) + outfile = str(tmpdir.join("xdr-writer-issue117" + self.ext)) with mda.Writer(outfile, n_atoms=universe.atoms.n_atoms) as W: for ts in universe.trajectory: W.write(universe) @@ -571,9 +631,12 @@ def test_write_trajectory(self, universe, tmpdir): written_ts._pos, orig_ts._pos, self.prec, - err_msg=("coordinate mismatch between original and written " - f"trajectory at frame {orig_ts.frame:d} (orig) vs " - f"{orig_ts.frame:d} (written)")) + err_msg=( + "coordinate mismatch between original and written " + f"trajectory at frame {orig_ts.frame:d} (orig) vs " + f"{orig_ts.frame:d} (written)" + ), + ) class TestXTCWriterIssue117(_GromacsWriterIssue117): @@ -596,7 +659,8 @@ def test_triclinic_box(): new_unitcell, unitcell, 3, - err_msg="unitcell round-trip connversion failed (Issue 61)") + err_msg="unitcell round-trip connversion failed (Issue 61)", + ) class XTCReference(BaseReference): @@ -606,7 +670,7 @@ def __init__(self): self.topology = COORDINATES_TOPOLOGY self.reader = mda.coordinates.XTC.XTCReader self.writer = mda.coordinates.XTC.XTCWriter - self.ext = 'xtc' + self.ext = "xtc" self.prec = 3 self.changing_dimensions = True @@ -625,7 +689,7 @@ def ref(): return XTCReference() def test_different_precision(self, ref, tmpdir): - out = 'precision-test' + ref.ext + out = "precision-test" + ref.ext # store more then 9 atoms to enable compression n_atoms = 40 with tmpdir.as_cwd(): @@ -648,7 +712,7 @@ def __init__(self): self.changing_dimensions = True self.reader = mda.coordinates.TRR.TRRReader self.writer = mda.coordinates.TRR.TRRWriter - self.ext = 'trr' + self.ext = "trr" self.prec = 3 self.first_frame.velocities = self.first_frame.positions / 10 self.first_frame.forces = self.first_frame.positions / 100 @@ -687,17 +751,19 @@ def ref(): # tests writing and reading in one! def test_lambda(self, ref, universe, tmpdir): - outfile = 'write-lambda-test' + ref.ext + outfile = "write-lambda-test" + ref.ext with tmpdir.as_cwd(): with ref.writer(outfile, universe.trajectory.n_atoms) as W: for i, ts in enumerate(universe.trajectory): - ts.data['lambda'] = i / float(universe.trajectory.n_frames) + ts.data["lambda"] = i / float(universe.trajectory.n_frames) W.write(universe) 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): @@ -705,19 +771,20 @@ class _GromacsReader_offsets(object): # This base class assumes same lengths and dt for XTC and TRR test cases! filename = None ref_unitcell = np.array( - [80.017, 80.017, 80.017, 60., 60., 90.], dtype=np.float32) + [80.017, 80.017, 80.017, 60.0, 60.0, 90.0], dtype=np.float32 + ) # computed with Gromacs: 362.26999999999998 nm**3 * 1000 A**3/nm**3 ref_volume = 362270.0 ref_offsets = None _reader = None prec = 3 - @pytest.fixture(scope='class') + @pytest.fixture(scope="class") def traj(self, tmpdir_factory): # copy of original test trajectory in a temporary folder. This is # needed since offsets are automatically generated in the same # directory. Here we also clean up nicely all files we generate - tmpdir = tmpdir_factory.mktemp('xtc') + tmpdir = tmpdir_factory.mktemp("xtc") shutil.copy(self.filename, str(tmpdir)) traj = str(tmpdir.join(os.path.basename(self.filename))) # ensure initialization of offsets @@ -733,30 +800,34 @@ def test_offsets(self, trajectory, traj): assert_almost_equal( trajectory._xdr.offsets, self.ref_offsets, - err_msg="wrong frame offsets") + err_msg="wrong frame offsets", + ) outfile_offsets = XDR.offsets_filename(traj) saved_offsets = XDR.read_numpy_offsets(outfile_offsets) - assert isinstance(saved_offsets, dict), \ - "read_numpy_offsets did not return a dict" + assert isinstance( + saved_offsets, dict + ), "read_numpy_offsets did not return a dict" assert_almost_equal( trajectory._xdr.offsets, - saved_offsets['offsets'], - err_msg="error saving frame offsets") + saved_offsets["offsets"], + err_msg="error saving frame offsets", + ) assert_almost_equal( self.ref_offsets, - saved_offsets['offsets'], - err_msg="saved frame offsets don't match " - "the known ones") + saved_offsets["offsets"], + err_msg="saved frame offsets don't match " "the known ones", + ) trajectory._load_offsets() assert_almost_equal( trajectory._xdr.offsets, self.ref_offsets, - err_msg="error loading frame offsets") - assert_equal(saved_offsets['ctime'], os.path.getctime(traj)) - assert_equal(saved_offsets['size'], os.path.getsize(traj)) + err_msg="error loading frame offsets", + ) + assert_equal(saved_offsets["ctime"], os.path.getctime(traj)) + assert_equal(saved_offsets["size"], os.path.getsize(traj)) def test_reload_offsets(self, traj): self._reader(traj, refresh_offsets=True) @@ -766,8 +837,12 @@ def test_nonexistent_offsets_file(self, traj): outfile_offsets = XDR.offsets_filename(traj) with patch.object(np, "load") as np_load_mock: np_load_mock.side_effect = IOError - with pytest.warns(UserWarning, match=re.escape( - f"Failed to load offsets file {outfile_offsets}")): + with pytest.warns( + UserWarning, + match=re.escape( + f"Failed to load offsets file {outfile_offsets}" + ), + ): saved_offsets = XDR.read_numpy_offsets(outfile_offsets) assert saved_offsets == False @@ -777,8 +852,12 @@ def test_corrupted_offsets_file(self, traj): outfile_offsets = XDR.offsets_filename(traj) with patch.object(np, "load") as np_load_mock: np_load_mock.side_effect = ValueError - with pytest.warns(UserWarning, match=re.escape( - f"Failed to load offsets file {outfile_offsets}")): + with pytest.warns( + UserWarning, + match=re.escape( + f"Failed to load offsets file {outfile_offsets}" + ), + ): saved_offsets = XDR.read_numpy_offsets(outfile_offsets) assert saved_offsets == False @@ -788,16 +867,18 @@ def test_reload_offsets_if_offsets_readin_io_fails(self, trajectory): # ensure that offsets are then read-in from the trajectory with patch.object(np, "load") as np_load_mock: np_load_mock.side_effect = IOError - with (pytest.warns(UserWarning, - match="Failed to load offsets file") and - pytest.warns(UserWarning, - match="reading offsets from trajectory instead")): + with pytest.warns( + UserWarning, match="Failed to load offsets file" + ) and pytest.warns( + UserWarning, match="reading offsets from trajectory instead" + ): trajectory._load_offsets() assert_almost_equal( trajectory._xdr.offsets, self.ref_offsets, - err_msg="error loading frame offsets") + err_msg="error loading frame offsets", + ) def test_reload_offsets_if_offsets_readin_value_fails(self, trajectory): # force the np.load call that is called in read_numpy_offsets @@ -810,7 +891,8 @@ def test_reload_offsets_if_offsets_readin_value_fails(self, trajectory): assert_almost_equal( trajectory._xdr.offsets, self.ref_offsets, - err_msg="error loading frame offsets") + err_msg="error loading frame offsets", + ) def test_persistent_offsets_size_mismatch(self, traj): # check that stored offsets are not loaded when trajectory @@ -818,11 +900,12 @@ def test_persistent_offsets_size_mismatch(self, traj): fname = XDR.offsets_filename(traj) saved_offsets = XDR.read_numpy_offsets(fname) - assert isinstance(saved_offsets, dict), \ - "read_numpy_offsets did not return a dict" + assert isinstance( + saved_offsets, dict + ), "read_numpy_offsets did not return a dict" - saved_offsets['size'] += 1 - with open(fname, 'wb') as f: + saved_offsets["size"] += 1 + with open(fname, "wb") as f: np.savez(f, **saved_offsets) with pytest.warns(UserWarning, match="Reload offsets"): @@ -834,11 +917,12 @@ def test_persistent_offsets_ctime_mismatch(self, traj): fname = XDR.offsets_filename(traj) saved_offsets = XDR.read_numpy_offsets(fname) - assert isinstance(saved_offsets, dict), \ - "read_numpy_offsets did not return a dict" + assert isinstance( + saved_offsets, dict + ), "read_numpy_offsets did not return a dict" - saved_offsets['ctime'] += 1 - with open(fname, 'wb') as f: + saved_offsets["ctime"] += 1 + with open(fname, "wb") as f: np.savez(f, **saved_offsets) with pytest.warns(UserWarning, match="Reload offsets"): @@ -850,10 +934,11 @@ def test_persistent_offsets_natoms_mismatch(self, traj): fname = XDR.offsets_filename(traj) saved_offsets = XDR.read_numpy_offsets(fname) - assert isinstance(saved_offsets, dict), \ - "read_numpy_offsets did not return a dict" + assert isinstance( + saved_offsets, dict + ), "read_numpy_offsets did not return a dict" - saved_offsets['n_atoms'] += 1 + saved_offsets["n_atoms"] += 1 np.savez(fname, **saved_offsets) with pytest.warns(UserWarning, match="Reload offsets"): @@ -863,11 +948,12 @@ def test_persistent_offsets_last_frame_wrong(self, traj): fname = XDR.offsets_filename(traj) saved_offsets = XDR.read_numpy_offsets(fname) - assert isinstance(saved_offsets, dict), \ - "read_numpy_offsets did not return a dict" + assert isinstance( + saved_offsets, dict + ), "read_numpy_offsets did not return a dict" idx_frame = 3 - saved_offsets['offsets'][idx_frame] += 42 + saved_offsets["offsets"][idx_frame] += 42 np.savez(fname, **saved_offsets) with pytest.warns(UserWarning, match="seek failed"): @@ -878,11 +964,12 @@ def test_unsupported_format(self, traj): fname = XDR.offsets_filename(traj) saved_offsets = XDR.read_numpy_offsets(fname) - assert isinstance(saved_offsets, dict), \ - "read_numpy_offsets did not return a dict" + assert isinstance( + saved_offsets, dict + ), "read_numpy_offsets did not return a dict" idx_frame = 3 - saved_offsets.pop('n_atoms') + saved_offsets.pop("n_atoms") np.savez(fname, **saved_offsets) # ok as long as this doesn't throw @@ -894,28 +981,32 @@ def test_unsupported_format(self, traj): def test_persistent_offsets_readonly(self, tmpdir): shutil.copy(self.filename, str(tmpdir)) - if os.name == 'nt': + if os.name == "nt": # Windows platform has a unique way to deny write access - subprocess.call("icacls {fname} /deny Users:W".format(fname=tmpdir), - shell=True) + subprocess.call( + "icacls {fname} /deny Users:W".format(fname=tmpdir), shell=True + ) else: os.chmod(str(tmpdir), 0o555) filename = str(tmpdir.join(os.path.basename(self.filename))) # try to write a offsets file - with (pytest.warns(UserWarning, match="Couldn't save offsets") and - pytest.warns(UserWarning, match="Cannot write")): + with pytest.warns( + UserWarning, match="Couldn't save offsets" + ) and pytest.warns(UserWarning, match="Cannot write"): self._reader(filename) assert_equal(os.path.exists(XDR.offsets_filename(filename)), False) # check the lock file is not created as well. - assert_equal(os.path.exists(XDR.offsets_filename(filename, - ending='.lock')), False) + assert_equal( + os.path.exists(XDR.offsets_filename(filename, ending=".lock")), + False, + ) # pre-teardown permission fix - leaving permission blocked dir # is problematic on py3.9 + Windows it seems. See issue # [4123](https://github.com/MDAnalysis/mdanalysis/issues/4123) # for more details. - if os.name == 'nt': + if os.name == "nt": subprocess.call(f"icacls {tmpdir} /grant Users:W", shell=True) else: os.chmod(str(tmpdir), 0o777) @@ -923,27 +1014,48 @@ def test_persistent_offsets_readonly(self, tmpdir): shutil.rmtree(tmpdir) def test_offset_lock_created(self): - assert os.path.exists(XDR.offsets_filename(self.filename, - ending='lock')) + assert os.path.exists( + XDR.offsets_filename(self.filename, ending="lock") + ) class TestXTCReader_offsets(_GromacsReader_offsets): __test__ = True filename = XTC - ref_offsets = np.array([ - 0, 165188, 330364, 495520, 660708, 825872, 991044, 1156212, 1321384, - 1486544 - ]) + ref_offsets = np.array( + [ + 0, + 165188, + 330364, + 495520, + 660708, + 825872, + 991044, + 1156212, + 1321384, + 1486544, + ] + ) _reader = mda.coordinates.XTC.XTCReader class TestTRRReader_offsets(_GromacsReader_offsets): __test__ = True filename = TRR - ref_offsets = np.array([ - 0, 1144464, 2288928, 3433392, 4577856, 5722320, 6866784, 8011248, - 9155712, 10300176 - ]) + ref_offsets = np.array( + [ + 0, + 1144464, + 2288928, + 3433392, + 4577856, + 5722320, + 6866784, + 8011248, + 9155712, + 10300176, + ] + ) _reader = mda.coordinates.TRR.TRRReader diff --git a/testsuite/MDAnalysisTests/coordinates/test_xyz.py b/testsuite/MDAnalysisTests/coordinates/test_xyz.py index ac68e4312c..c9e5eb8241 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_xyz.py +++ b/testsuite/MDAnalysisTests/coordinates/test_xyz.py @@ -32,12 +32,16 @@ from MDAnalysis.coordinates.XYZ import XYZWriter from MDAnalysisTests.datafiles import COORDINATES_XYZ, COORDINATES_XYZ_BZ2 -from MDAnalysisTests.coordinates.base import (MultiframeReaderTest, BaseReference, - BaseWriterTest) +from MDAnalysisTests.coordinates.base import ( + MultiframeReaderTest, + BaseReference, + BaseWriterTest, +) from MDAnalysisTests import make_Universe from MDAnalysis import __version__ + class XYZReference(BaseReference): def __init__(self): super(XYZReference, self).__init__() @@ -46,7 +50,7 @@ def __init__(self): self.topology = COORDINATES_XYZ self.reader = mda.coordinates.XYZ.XYZReader self.writer = mda.coordinates.XYZ.XYZWriter - self.ext = 'xyz' + self.ext = "xyz" self.volume = 0 self.dimensions = None self.container_format = True @@ -71,9 +75,9 @@ def ref(): return XYZReference() def test_write_selection(self, ref, universe, reader, tmpdir): - sel_str = 'name CA' + sel_str = "name CA" sel = universe.select_atoms(sel_str) - outfile = 'write-selection-test' + ref.ext + outfile = "write-selection-test" + ref.ext with tmpdir.as_cwd(): with ref.writer(outfile, sel.n_atoms) as W: @@ -83,13 +87,17 @@ def test_write_selection(self, ref, universe, reader, tmpdir): copy = ref.reader(outfile) for orig_ts, copy_ts in zip(universe.trajectory, copy): assert_almost_equal( - copy_ts._pos, sel.atoms.positions, ref.prec, + copy_ts._pos, + sel.atoms.positions, + ref.prec, err_msg="coordinate mismatch between original and written " - "trajectory at frame {} (orig) vs {} (copy)".format( - orig_ts.frame, copy_ts.frame)) + "trajectory at frame {} (orig) vs {} (copy)".format( + orig_ts.frame, copy_ts.frame + ), + ) def test_write_different_models_in_trajectory(self, ref, universe, tmpdir): - outfile = 'write-models-in-trajectory' + ref.ext + outfile = "write-models-in-trajectory" + ref.ext # n_atoms should match for each TimeStep if it was specified with tmpdir.as_cwd(): with ref.writer(outfile, n_atoms=4) as w: @@ -97,19 +105,25 @@ def test_write_different_models_in_trajectory(self, ref, universe, tmpdir): w.write(universe) def test_no_conversion(self, ref, universe, reader, tmpdir): - outfile = 'write-no-conversion' + ref.ext + outfile = "write-no-conversion" + ref.ext with tmpdir.as_cwd(): with ref.writer(outfile, convert_units=False) as w: for ts in universe.trajectory: w.write(universe) self._check_copy(outfile, ref, reader) - @pytest.mark.parametrize("remarkout, remarkin", - [ + @pytest.mark.parametrize( + "remarkout, remarkin", + [ 2 * ["Curstom Remark"], 2 * [""], - [None, "frame 0 | Written by MDAnalysis XYZWriter (release {0})".format(__version__)], - ] + [ + None, + "frame 0 | Written by MDAnalysis XYZWriter (release {0})".format( + __version__ + ), + ], + ], ) def test_remark(self, universe, remarkout, remarkin, ref, tmpdir): outfile = "write-remark.xyz" @@ -138,7 +152,7 @@ class XYZ_BZ_Reference(XYZReference): def __init__(self): super(XYZ_BZ_Reference, self).__init__() self.trajectory = COORDINATES_XYZ_BZ2 - self.ext = 'xyz.bz2' + self.ext = "xyz.bz2" class Test_XYZBZReader(TestXYZReader): @@ -158,12 +172,12 @@ def ref(): class TestXYZWriterNames(object): @pytest.fixture() def outfile(self, tmpdir): - return str(tmpdir.join('/outfile.xyz')) + return str(tmpdir.join("/outfile.xyz")) def test_no_names(self, outfile): """Atoms should all be named 'X'""" u = make_Universe(trajectory=True) - + wmsg = "does not have atom elements or names" with pytest.warns(UserWarning, match=wmsg): @@ -172,29 +186,29 @@ def test_no_names(self, outfile): w.close() u2 = mda.Universe(outfile) - assert all(u2.atoms.names == 'X') + assert all(u2.atoms.names == "X") @pytest.mark.parametrize("attr", ["elements", "names"]) def test_elements_or_names(self, outfile, attr): u = mda.Universe.empty(n_atoms=5, trajectory=True) - u.add_TopologyAttr(attr, values=['Te', 'S', 'Ti', 'N', 'Ga']) + u.add_TopologyAttr(attr, values=["Te", "S", "Ti", "N", "Ga"]) with mda.Writer(outfile) as w: w.write(u) with open(outfile, "r") as r: - names = ''.join(l.split()[0].strip() for l in r.readlines()[2:-1]) + names = "".join(l.split()[0].strip() for l in r.readlines()[2:-1]) - assert names[:-1].lower() == 'testing' + assert names[:-1].lower() == "testing" def test_elements_and_names(self, outfile): """Should always default to elements over names""" u = mda.Universe.empty(n_atoms=5, trajectory=True) - u.add_TopologyAttr('elements', values=['Te', 'S', 'Ti', 'N', 'Ga']) - u.add_TopologyAttr('names', values=['A', 'B', 'C', 'D', 'E']) + u.add_TopologyAttr("elements", values=["Te", "S", "Ti", "N", "Ga"]) + u.add_TopologyAttr("names", values=["A", "B", "C", "D", "E"]) with mda.Writer(outfile) as w: w.write(u) diff --git a/testsuite/pyproject.toml b/testsuite/pyproject.toml index 8e422352e1..8c12d164e7 100644 --- a/testsuite/pyproject.toml +++ b/testsuite/pyproject.toml @@ -164,6 +164,7 @@ setup\.py | MDAnalysisTests/transformations/.*\.py | MDAnalysisTests/guesser/.*\.py | MDAnalysisTests/converters/.*\.py +| MDAnalysisTests/coordinates/.*\.py | MDAnalysisTests/data/.*\.py | MDAnalysisTests/formats/.*\.py | MDAnalysisTests/parallelism/.*\.py