diff --git a/package/MDAnalysis/analysis/encore/similarity.py b/package/MDAnalysis/analysis/encore/similarity.py index c8e0151dff6..d0befb76597 100644 --- a/package/MDAnalysis/analysis/encore/similarity.py +++ b/package/MDAnalysis/analysis/encore/similarity.py @@ -19,8 +19,7 @@ # MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # -""" -================================================================================= +"""================================================================================= Ensemble Similarity Calculations --- :mod:`MDAnalysis.analysis.encore.similarity` ================================================================================= @@ -56,9 +55,12 @@ References ========== - .. [Lindorff-Larsen2009] Similarity Measures for Protein Ensembles. Lindorff-Larsen, K. Ferkinghoff-Borg, J. PLoS ONE 2008, 4, e4203. +.. [Lindorff-Larsen2009] Similarity Measures for Protein + Ensembles. Lindorff-Larsen, K. Ferkinghoff-Borg, J. PLoS ONE 2008, 4, e4203. - .. [Tiberti2015] ENCORE: Software for Quantitative Ensemble Comparison. Matteo Tiberti, Elena Papaleo, Tone Bengtsen, Wouter Boomsma, Kresten Lindorff- Larsen. PLoS Comput Biol. 2015, 11 +.. [Tiberti2015] ENCORE: Software for Quantitative Ensemble Comparison. Matteo + Tiberti, Elena Papaleo, Tone Bengtsen, Wouter Boomsma, Kresten + Lindorff-Larsen. PLoS Comput Biol. 2015, 11, e1004415. .. _Examples: Examples @@ -166,7 +168,6 @@ .. All functions are included via automodule :members:. - """ from __future__ import print_function, division, absolute_import from six.moves import range, zip diff --git a/package/MDAnalysis/analysis/encore/utils.py b/package/MDAnalysis/analysis/encore/utils.py index a552ba74af3..f65d925f812 100644 --- a/package/MDAnalysis/analysis/encore/utils.py +++ b/package/MDAnalysis/analysis/encore/utils.py @@ -21,6 +21,7 @@ # from __future__ import division, absolute_import from six.moves import range +import numbers from multiprocessing.sharedctypes import SynchronizedArray from multiprocessing import Process, Manager from joblib import cpu_count @@ -68,7 +69,7 @@ def __init__(self, size, metadata=None, loadfile=None): self.size = size if loadfile: self.loadz(loadfile) - elif isinstance(size, int): + elif isinstance(size, numbers.Integral): self.size = size self._elements = np.zeros((size + 1) * size // 2, dtype=np.float64) elif isinstance(size, SynchronizedArray): diff --git a/package/MDAnalysis/auxiliary/XVG.py b/package/MDAnalysis/auxiliary/XVG.py index 8b181164f11..83cbd8d13a9 100644 --- a/package/MDAnalysis/auxiliary/XVG.py +++ b/package/MDAnalysis/auxiliary/XVG.py @@ -25,14 +25,14 @@ ======================================================== xvg files are produced by Gromacs during simulation or analysis, formatted -for plotting data with Grace. +for plotting data with Grace. -Data is column-formatted; time/data selection is enabled by providing column -indices. +Data is column-formatted; time/data selection is enabled by providing column +indices. Note ---- -By default, the time of each step is assumed to be stored in the first column, +By default, the time of each step is assumed to be stored in the first column, in units of ps. @@ -42,17 +42,17 @@ XVG Readers ----------- -The default :class:`XVGReader` reads and stores the full contents of the .xvg -file on initialisation, while a second reader (:class:`XVGFileReader`) that -reads steps one at a time as required is also provided for when a lower memory +The default :class:`XVGReader` reads and stores the full contents of the .xvg +file on initialisation, while a second reader (:class:`XVGFileReader`) that +reads steps one at a time as required is also provided for when a lower memory footprint is desired. Note ---- Data is assumed to be time-ordered. -Multiple datasets, separated in the .xvg file by '&', are currently not -supported (the readers will stop at the first line starting '&'). +Multiple datasets, separated in the .xvg file by '&', are currently not +supported (the readers will stop at the first line starting '&'). .. autoclass:: XVGReader @@ -69,6 +69,7 @@ from six.moves import range +import numbers import os import numpy as np from . import base @@ -106,8 +107,8 @@ def uncomment(lines): class XVGStep(base.AuxStep): """ AuxStep class for .xvg file format. - Extends the base AuxStep class to allow selection of time and - data-of-interest fields (by column index) from the full set of data read + Extends the base AuxStep class to allow selection of time and + data-of-interest fields (by column index) from the full set of data read each step. Parameters @@ -134,7 +135,7 @@ def _select_time(self, key): if key is None: # here so that None is a valid value; just return return - if isinstance(key, int): + if isinstance(key, numbers.Integral): return self._select_data(key) else: raise ValueError('Time selector must be single index') @@ -143,7 +144,7 @@ def _select_data(self, key): if key is None: # here so that None is a valid value; just return return - if isinstance(key, int): + if isinstance(key, numbers.Integral): try: return self._data[key] except IndexError: @@ -156,15 +157,15 @@ def _select_data(self, key): class XVGReader(base.AuxReader): """ Auxiliary reader to read data from an .xvg file. - Detault reader for .xvg files. All data from the file will be read and stored + Detault reader for .xvg files. All data from the file will be read and stored on initialisation. - + Parameters ---------- filename : str Location of the file containing the auxiliary data. **kwargs - Other AuxReader options. + Other AuxReader options. See Also -------- @@ -172,7 +173,7 @@ class XVGReader(base.AuxReader): Note ---- - The file is assumed to be of a size such that reading and storing the full + The file is assumed to be of a size such that reading and storing the full contents is practical. """ @@ -193,7 +194,7 @@ def __init__(self, filename, **kwargs): # check the number of columns is consistent if len(auxdata_values[i]) != len(auxdata_values[0]): raise ValueError('Step {0} has {1} columns instead of ' - '{2}'.format(i, auxdata_values[i], + '{2}'.format(i, auxdata_values[i], auxdata_values[0])) self._auxdata_values = np.array(auxdata_values) self._n_steps = len(self._auxdata_values) @@ -223,13 +224,17 @@ def _read_next_step(self): raise StopIteration def _go_to_step(self, i): - """ Move to and read i-th auxiliary step. + """ Move to and read i-th auxiliary step. Parameters ---------- - i : int + i: int Step number (0-indexed) to move to + Returns + ------- + :class:`XVGStep` + Raises ------ ValueError @@ -256,16 +261,16 @@ def read_all_times(self): class XVGFileReader(base.AuxFileReader): """ Auxiliary reader to read (step at a time) from an .xvg file. - An alternative XVG reader which reads each step from the .xvg file as - needed (rather than reading and storing all from the start), for a lower - memory footprint. - + An alternative XVG reader which reads each step from the .xvg file as + needed (rather than reading and storing all from the start), for a lower + memory footprint. + Parameters ---------- filename : str Location of the file containing the auxiliary data. **kwargs - Other AuxReader options. + Other AuxReader options. See Also -------- @@ -336,7 +341,7 @@ def _count_n_steps(self): try: return len(self._times) except AttributeError: - # might as well build _times now, since we'll need to iterate + # might as well build _times now, since we'll need to iterate # through anyway self._times = self.read_all_times() return len(self.read_all_times()) diff --git a/package/MDAnalysis/auxiliary/base.py b/package/MDAnalysis/auxiliary/base.py index 945c6a34421..63a790719ed 100644 --- a/package/MDAnalysis/auxiliary/base.py +++ b/package/MDAnalysis/auxiliary/base.py @@ -43,10 +43,12 @@ from six.moves import range import os -import numpy as np +import numbers import math import warnings +import numpy as np + from ..lib.util import asiterable, anyopen from . import _AUXREADERS @@ -68,7 +70,7 @@ def __init__(cls, name, bases, classdict): class AuxStep(object): """Base class for auxiliary timesteps. - Stores the auxiliary data for the current auxiliary step. On creation, + Stores the auxiliary data for the current auxiliary step. On creation, ``step`` is set to -1. Parameters @@ -77,7 +79,7 @@ class AuxStep(object): Change in time between auxiliary steps (in ps). If not specified, will attempt to determine from auxiliary data; otherwise defaults to 1 ps. Ignored if ``constant_dt`` is False. - initial_time : float, optional + initial_time : float, optional Time of first auxiliary step (in ps). If not specified, will attempt to determine from auxiliary data; otherwise defaults to 0 ps. Ignored if ``constant_dt`` is False. @@ -89,14 +91,14 @@ class AuxStep(object): * dt + initial_time`` data_selector: optional Key(s) to select auxiliary data values of interest from the full set of - data read for each step, if data selection is enabled by the reader; + data read for each step, if data selection is enabled by the reader; type will vary depending on the auxiliary data format (see individual - AuxReader documentation). + AuxReader documentation). If ``None`` (default value), the full set of data is returned. constant_dt : bool, optional - (Default: True) Set to False if ``dt`` is not constant - throughout the auxiliary data set, in which case a valid - ``time_selector`` must be provided. + (Default: True) Set to False if ``dt`` is not constant + throughout the auxiliary data set, in which case a valid + ``time_selector`` must be provided. Attributes ---------- @@ -104,7 +106,7 @@ class AuxStep(object): Number of the current auxiliary step (0-based). """ - def __init__(self, dt=1, initial_time=0, time_selector=None, + def __init__(self, dt=1, initial_time=0, time_selector=None, data_selector=None, constant_dt=True): self.step = -1 self._initial_time = initial_time @@ -121,16 +123,16 @@ def __init__(self, dt=1, initial_time=0, time_selector=None, def time(self): """ Time in ps of current auxiliary step (as float). - Read from the set of auxiliary data read each step if time selection - is enabled and a valid ``time_selector`` is specified; otherwise + Read from the set of auxiliary data read each step if time selection + is enabled and a valid ``time_selector`` is specified; otherwise calculated as ``step * dt + initial_time``. """ if self._time_selector is not None: return self._select_time(self._time_selector) elif self._constant_dt: # default to calculting time... - return self.step * self._dt + self._initial_time - else: + return self.step * self._dt + self._initial_time + else: raise ValueError("If dt is not constant, must have a valid " "time selector") @@ -140,7 +142,7 @@ def data(self): """ Auxiliary values of interest for the current step (as ndarray). Read from the full set of data read for each step if data selection is - enabled and a valid ``data_selector`` is specified; otherwise + enabled and a valid ``data_selector`` is specified; otherwise defaults to the full set of data. """ if self._data_selector is not None: @@ -152,10 +154,10 @@ def data(self): def _time_selector(self): """ 'Key' to select time from the full set of data read in each step. - Will be passed to ``_select_time()``, defined separately for each - auxiliary format, when returning the time of the current step. + Will be passed to ``_select_time()``, defined separately for each + auxiliary format, when returning the time of the current step. Format will depend on the auxiliary format. e.g. for the XVGReader, - this is an index and `_select_time()` returns the value in that column + this is an index and ``_select_time()`` returns the value in that column of the current step data. Defaults to 'None' if time selection is not enabled. @@ -177,18 +179,18 @@ def _time_selector(self, new): warnings.warn("{} does not support time selection".format( self.__class__.__name__)) else: - # check *new* is valid before setting; _select_time should raise + # check *new* is valid before setting; _select_time should raise # an error if not select(new) self._time_selector_ = new @property def _data_selector(self): - """ 'Key' to select values of interest from full set of auxiliary data. - These are the values that will be stored in ``data`` (and + """ 'Key' to select values of interest from full set of auxiliary data. + These are the values that will be stored in ``data`` (and ``frame_data`` and ``frame_rep``). - Will be passed to ``_select_data()``, defined separately for each + Will be passed to ``_select_data()``, defined separately for each auxiliary format, when returning the data of interest for the current step (``data``). Format will depend on the auxiliary format; e.g. for the XVGReader, this is a list of indices and `_select_data()` returns @@ -213,7 +215,7 @@ def _data_selector(self, new): warnings.warn("{} does not support data selection".format( self.__class__.__name__)) else: - # check *new* is valid before setting; _select_data should raise an + # check *new* is valid before setting; _select_data should raise an # error if not select(new) self._data_selector_ = new @@ -227,30 +229,30 @@ def _empty_data(self): Default behaviour here works when ``data`` is a ndarray of floats. May need to overwrite in individual format's AuxSteps. - """ + """ return np.full_like(self.data, np.nan) class AuxReader(six.with_metaclass(_AuxReaderMeta)): """ Base class for auxiliary readers. - Allows iteration over a set of data from a trajectory, additional - ('auxiliary') to the regular positions/velocities/etc. This auxiliary - data may be stored in e.g. an array or a separate file. + Allows iteration over a set of data from a trajectory, additional + ('auxiliary') to the regular positions/velocities/etc. This auxiliary + data may be stored in e.g. an array or a separate file. See the :ref:`Auxiliary API` for more on use. Parameters ---------- auxname : str, optional - Name for auxiliary data. When added to a trajectory, the representative - auxiliary value(s) for the timestep may be accessed as ``ts.aux.auxname`` + Name for auxiliary data. When added to a trajectory, the representative + auxiliary value(s) for the timestep may be accessed as ``ts.aux.auxname`` or ``ts.aux['auxname']``. represent_ts_as : str - Method to use to calculate representative value of auxiliary data for a + Method to use to calculate representative value of auxiliary data for a trajectory timestep. See :func:`calc_representative` for valid options. cutoff : float, optional - Auxiliary steps further from the trajectory timestep than *cutoff* + Auxiliary steps further from the trajectory timestep than *cutoff* (in ps) will be ignored when calculating representative values. If -1 (default), all auxiliary steps assigned to that timestep will be used. **kwargs @@ -260,11 +262,11 @@ class AuxReader(six.with_metaclass(_AuxReaderMeta)): Attributes ---------- auxstep : - :class:`~AuxStep` object containing data for current step. + :class:`~AuxStep` object containing data for current step. frame_data : dict - Dictionary containing ``data`` from each auxiliary step assigned to the + Dictionary containing ``data`` from each auxiliary step assigned to the current trajectory timestep, indexed by the difference in time between - the step and trajectory timestep (i.e. ``auxstep.time - ts.time``; in ps) + the step and trajectory timestep (i.e. ``auxstep.time - ts.time``; in ps) frame_rep : ndarray Representative value(s) of auxiliary data for current trajectory timestep. @@ -280,10 +282,10 @@ class AuxReader(six.with_metaclass(_AuxReaderMeta)): # list of attributes required to recreate the auxiliary required_attrs = ['represent_ts_as', 'cutoff', 'dt', 'initial_time', - 'time_selector', 'data_selector', 'constant_dt', 'auxname', + 'time_selector', 'data_selector', 'constant_dt', 'auxname', 'format', '_auxdata'] - - def __init__(self, represent_ts_as='closest', auxname=None, cutoff=-1, + + def __init__(self, represent_ts_as='closest', auxname=None, cutoff=-1, **kwargs): # allow auxname to be optional for when using reader separate from # trajectory. @@ -296,7 +298,7 @@ def __init__(self, represent_ts_as='closest', auxname=None, cutoff=-1, self.auxstep = self._Auxstep(**kwargs) self._read_next_step() - # if dt is constant and auxiliary data includes time, calculate + # if dt is constant and auxiliary data includes time, calculate # initial time and dt if self.time_selector is not None and self.constant_dt: self.auxstep._initial_time = self.time @@ -325,14 +327,14 @@ def _restart(self): """ Reset back to start; calling next() should read first step. """ # Overwrite as appropriate self.auxstep.step = -1 - + def rewind(self): """ Return to and read first step. """ # Overwrite as appropriate # could also use _go_to_step(0) self._restart() return self._read_next_step() - + def _read_next_step(self): """ Move to next step and update auxstep. @@ -343,11 +345,11 @@ def _read_next_step(self): "BUG: Override _read_next_timestep() in auxiliary reader!") def update_ts(self, ts): - """ Read auxiliary steps corresponding to and update the trajectory + """ Read auxiliary steps corresponding to and update the trajectory timestep *ts*. Calls :meth:`read_ts`, then updates *ts* with the representative value. - ``auxname`` must be set; the representative value will be accessible in + ``auxname`` must be set; the representative value will be accessible in *ts* as ``ts.aux.auxname`` or ``ts.aux['auxname']``. Parameters @@ -359,7 +361,7 @@ def update_ts(self, ts): Returns ------- :class:`~MDAnalysis.coordinates.base.Timestep` - *ts* with the representative auxiliary + *ts* with the representative auxiliary value in ``ts.aux`` be updated appropriately. Raises @@ -379,13 +381,13 @@ def update_ts(self, ts): setattr(ts.aux, self.auxname, self.frame_rep) return ts - def read_ts(self, ts): + def read_ts(self, ts): """ Read auxiliary steps corresponding to the trajectory timestep *ts*. Read the auxiliary steps 'assigned' to *ts* (the steps that are within ``ts.dt/2`` of of the trajectory timestep/frame - ie. closer to *ts* - than either the preceding or following frame). Then calculate a - 'representative value' for the timestep from the data in each of these + than either the preceding or following frame). Then calculate a + 'representative value' for the timestep from the data in each of these auxiliary steps. To update *ts* with the representative value, use ``update_ts`` instead. @@ -404,12 +406,12 @@ def read_ts(self, ts): ---- The auxiliary reader will end up positioned at the last step assigned to the trajectory frame or, if the frame includes no auxiliary steps, - (as when auxiliary data are less frequent), the most recent auxiliary + (as when auxiliary data are less frequent), the most recent auxiliary step before the frame. """ # Make sure our auxiliary step starts at the right point (just before - # the frame being read): the current step should be assigned to a - # previous frame, and the next step to either the frame being read or a + # the frame being read): the current step should be assigned to a + # previous frame, and the next step to either the frame being read or a # following frame. Move to right position if not. if not (self.step_to_frame(self.step, ts) < ts.frame and self.step_to_frame(self.step+1, ts) >= ts.frame): @@ -433,19 +435,19 @@ def step_to_frame(self, step, ts, return_time_diff=False): frame = floor((step_to_time(step) - time_frame_0 + ts.dt/2)/ts.dt)) The difference in time between the step and the calculated frame can - also optionally be returned with *return_time_diff*. + also optionally be returned with *return_time_diff*. Parameters ---------- step : int - Number of the auxiliary step to calculate closest trajectory frame + Number of the auxiliary step to calculate closest trajectory frame for. ts : :class:`~MDAnalysis.coordinates.base.Timestep` object - (Any) timestep from the trajectory the calculated frame number is to + (Any) timestep from the trajectory the calculated frame number is to correspond to. return_time_diff : bool, optional - (Default: False) Additionally return the time difference between - *step* and returned frame. + (Default: False) Additionally return the time difference between + *step* and returned frame. Returns ------- @@ -462,7 +464,7 @@ def step_to_frame(self, step, ts, return_time_diff=False): The returned frame number may be out of range for the trajectory. """ if step >= self.n_steps or step < 0: - return None + return None time_frame_0 = ts.time - ts.frame*ts.dt # assumes ts.dt is constant time_step = self.step_to_time(step) frame_index = int(math.floor((time_step-time_frame_0+ts.dt/2.)/ts.dt)) @@ -477,7 +479,7 @@ def move_to_ts(self, ts): """ Position auxiliary reader just before trajectory timestep *ts*. Calling ``next()`` should read the first auxiliary step 'assigned' to - the trajectory timestep *ts* or, if no auxiliary steps are + the trajectory timestep *ts* or, if no auxiliary steps are assigned to that timestep (as in the case of less frequent auxiliary data), the first auxiliary step after *ts*. @@ -509,10 +511,10 @@ def next_nonempty_frame(self, ts): """ Find the next trajectory frame for which a representative auxiliary value can be calculated. - That is, the next trajectory frame to which one or more auxiliary steps + That is, the next trajectory frame to which one or more auxiliary steps are assigned and fall within the cutoff. - Starts looking from the current step time. If the end of the auxiliary + Starts looking from the current step time. If the end of the auxiliary data is reached before a trajectory frame is found, None is returned. Parameters @@ -532,11 +534,11 @@ def next_nonempty_frame(self, ts): """ step = self.step while step < self.n_steps-1: - next_frame, time_diff = self.step_to_frame(self.step+1, ts, + next_frame, time_diff = self.step_to_frame(self.step+1, ts, return_time_diff=True) if self.cutoff != -1 and time_diff > self.cutoff: # 'representative values' will be NaN; check next step - step = step + 1 + step = step + 1 else: return next_frame # we ran out of auxiliary steps... @@ -545,24 +547,24 @@ def next_nonempty_frame(self, ts): def __getitem__(self, i): """ Return the AuxStep corresponding to the *i*-th auxiliary step(s) (0-based). Negative numbers are counted from the end. - - *i* may be an integer (in which case the corresponding AuxStep is - returned) or a list of integers or slice (in which case an iterator is + + *i* may be an integer (in which case the corresponding AuxStep is + returned) or a list of integers or slice (in which case an iterator is returned):: step_10 = aux_reader[10] - will move to step 10 of the auxiliary and return the :class:`AuxStep`. - By using a slice/list, we can iterated over specified steps in the + will move to step 10 of the auxiliary and return the :class:`AuxStep`. + By using a slice/list, we can iterated over specified steps in the auxiliary, e.g. when performing analysis :: for auxstep in aux_reader[100:200]: # analyse only steps 100 to 200 run_analysis(auxstep) - for auxstep in aux_reader[::10] # analyse every 10th step + for auxstep in aux_reader[::10] # analyse every 10th step run_analysis(auxstep) """ - if isinstance(i, int): + if isinstance(i, numbers.Integral): i = self._check_index(i) return self._go_to_step(i) @@ -573,13 +575,13 @@ def __getitem__(self, i): # default start to first frame (ie. 0) start = self._check_index(i.start) if i.start is not None else 0 # default stop to after last frame (i.e. n_steps) - # n_steps is a valid stop index but will fail _check_index; + # n_steps is a valid stop index but will fail _check_index; # deal with separately - stop = (i.stop if i.stop == self.n_steps - else self._check_index(i.stop) if i.stop is not None + stop = (i.stop if i.stop == self.n_steps + else self._check_index(i.stop) if i.stop is not None else self.n_steps) step = i.step or 1 - if not isinstance(step, int) or step < 1: + if not isinstance(step, numbers.Integral) or step < 1: raise ValueError("Step must be positive integer") # allow -ve? if start > stop: raise IndexError("Stop frame is lower than start frame") @@ -588,7 +590,7 @@ def __getitem__(self, i): raise TypeError("Index must be integer, list of integers or slice") def _check_index(self, i): - if not isinstance(i, (int, np.integer)): + if not isinstance(i, numbers.Integral): raise TypeError("Step indices must be integers") if i < 0: i = i + self.n_steps @@ -627,19 +629,19 @@ def _add_step_to_frame_data(self, ts_time): self.frame_data[time_diff] = self.auxstep.data def calc_representative(self): - """ Calculate representative auxiliary value(s) from the data in + """ Calculate representative auxiliary value(s) from the data in *frame_data*. - + Currently implemented options for calculating representative value are: - * `closest`: default; the value(s) from the step closest to in time + * `closest`: default; the value(s) from the step closest to in time to the trajectory timestep - * `average`: average of the value(s) from steps 'assigned' to the + * `average`: average of the value(s) from steps 'assigned' to the trajectory timestep. - Additionally, if ``cutoff`` is specified, only steps within this time - of the trajectory timestep are considered in calculating the + Additionally, if ``cutoff`` is specified, only steps within this time + of the trajectory timestep are considered in calculating the representative. If no auxiliary steps were assigned to the timestep, or none fall @@ -647,7 +649,7 @@ def calc_representative(self): Returns ------- - ndarray + ndarray Array of auxiliary value(s) 'representative' for the timestep. """ if self.cutoff == -1: @@ -672,7 +674,7 @@ def calc_representative(self): value = np.mean(np.array([val for val in cutoff_data.values()]), axis=0) return value - + def __enter__(self): return self @@ -696,9 +698,9 @@ def n_steps(self): def step_to_time(self, i): """ Return time of auxiliary step *i*. - Calculated using ``dt`` and ``initial_time`` if ``constant_dt`` is True; - otherwise from the list of times as read from the auxiliary data for - each step. + Calculated using ``dt`` and ``initial_time`` if ``constant_dt`` is True; + otherwise from the list of times as read from the auxiliary data for + each step. Parameters ---------- @@ -729,7 +731,7 @@ def step_to_time(self, i): @property def represent_ts_as(self): - """ Method by which 'representative' timestep values of auxiliary data + """ Method by which 'representative' timestep values of auxiliary data will be calculated. """ return self._represent_ts_as @@ -747,17 +749,17 @@ def __del__(self): self.close() def get_description(self): - """ Get the values of the parameters necessary for replicating the + """ Get the values of the parameters necessary for replicating the AuxReader. - An AuxReader can be duplicated using + An AuxReader can be duplicated using :func:`~MDAnalysis.auxiliary.core.auxreader`:: description = original_aux.get_description() new_aux = MDAnalysis.auxiliary.auxreader(**description) - The resulting dictionary may also be passed directly to - :meth:`~MDAnalysis.coordinates.base.ProtoReader.add_auxiliary` to + The resulting dictionary may also be passed directly to + :meth:`~MDAnalysis.coordinates.base.ProtoReader.add_auxiliary` to reload an auxiliary into a trajectory:: trajectory.add_auxiliary(**description) @@ -765,10 +767,10 @@ def get_description(self): Returns ------- dict - Key-word arguments and values that can be used to replicate the + Key-word arguments and values that can be used to replicate the AuxReader. """ - description = {attr.strip('_'): getattr(self, attr) + description = {attr.strip('_'): getattr(self, attr) for attr in self.required_attrs} return description @@ -780,7 +782,7 @@ def __eq__(self, other): @property def step(self): - """Number of the current auxiliary step (as stored in ``auxstep``; + """Number of the current auxiliary step (as stored in ``auxstep``; 0-based).""" return self.auxstep.step @@ -791,7 +793,7 @@ def time(self): @property def dt(self): - """Change in time between auxiliary steps (as stored in ``auxstep``; + """Change in time between auxiliary steps (as stored in ``auxstep``; in ps)""" return self.auxstep._dt @@ -806,12 +808,12 @@ def time_selector(self): As stored in ``austep``. Type differs between auxiliary formats, depending how the data for each - step is read in and stored; e.g. data from .xvg files is read in as a - list and `time_selector` must be a valid index. If time selection is not - enabled by the reader, ``time_selector`` will default to ``None``. + step is read in and stored; e.g. data from .xvg files is read in as a + list and `time_selector` must be a valid index. If time selection is not + enabled by the reader, ``time_selector`` will default to ``None``. See each individual auxiliary reader. - """ + """ return self.auxstep._time_selector @time_selector.setter @@ -819,7 +821,7 @@ def time_selector(self, new): olf = self.auxstep._time_selector self.auxstep._time_selector = new if old != new: - # if constant_dt is False and so we're using a _times list, this will + # if constant_dt is False and so we're using a _times list, this will # now be made invalid try: del(self._times) @@ -828,14 +830,14 @@ def time_selector(self, new): @property def data_selector(self): - """Key(s) to select auxiliary data values of interest from the full set + """Key(s) to select auxiliary data values of interest from the full set of data read for each step (as stored in ``auxstep``). Type differs between auxiliary formats, depending how the data for each step is read in and stored - e.g. data from .xvg files is read in as - a list and `data_selector` must be a list of valid indicies. If data - selection is not enabled by the reader, ``data_selector`` will default - to ``None``. + a list and `data_selector` must be a list of valid indicies. If data + selection is not enabled by the reader, ``data_selector`` will default + to ``None``. See each individual auxiliary reader. """ @@ -847,7 +849,7 @@ def data_selector(self, new): @property def constant_dt(self): - """ True if ``dt`` is constant throughout the auxiliary (as stored in + """ True if ``dt`` is constant throughout the auxiliary (as stored in ``auxstep``) """ return self.auxstep._constant_dt @@ -859,7 +861,7 @@ def constant_dt(self, new): class AuxFileReader(AuxReader): """ Base class for auxiliary readers that read from file. - Extends AuxReader with attributes and methods particular to reading + Extends AuxReader with attributes and methods particular to reading auxiliary data from an open file, for use when auxiliary files may be too large to read in at once. @@ -868,7 +870,7 @@ class AuxFileReader(AuxReader): filename : str Location of the file containing the auxiliary data. **kwargs - Other AuxReader options. + Other AuxReader options. See also -------- @@ -880,7 +882,7 @@ class AuxFileReader(AuxReader): File object for the auxiliary file. """ - + def __init__(self, filename, **kwargs): self.auxfile = anyopen(filename) self._auxdata = os.path.abspath(filename) @@ -897,7 +899,7 @@ def _restart(self): """ Reposition to just before first step. """ self.auxfile.seek(0) self.auxstep.step = -1 - + def _reopen(self): """ Close and then reopen *auxfile*. """ if self.auxfile != None: @@ -906,7 +908,7 @@ def _reopen(self): self.auxstep.step = -1 def _go_to_step(self, i): - """ Move to and read i-th auxiliary step. + """ Move to and read i-th auxiliary step. Parameters ---------- diff --git a/package/MDAnalysis/coordinates/CRD.py b/package/MDAnalysis/coordinates/CRD.py index 21865f12e10..70e7b857575 100644 --- a/package/MDAnalysis/coordinates/CRD.py +++ b/package/MDAnalysis/coordinates/CRD.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -45,8 +45,8 @@ class CRDReader(base.SingleFrameReaderBase): """CRD reader that implements the standard and extended CRD coordinate formats .. versionchanged:: 0.11.0 - Now returns a ValueError instead of FormatError - Frames now 0-based instead of 1-based + Now returns a ValueError instead of FormatError. + Frames now 0-based instead of 1-based. """ format = 'CRD' units = {'time': None, 'length': 'Angstrom'} @@ -99,11 +99,14 @@ def _read_first_frame(self): def Writer(self, filename, **kwargs): """Returns a CRDWriter for *filename*. - :Arguments: - *filename* - filename of the output CRD file + Parameters + ---------- + filename: str + filename of the output CRD file - :Returns: :class:`CRDWriter` + Returns + ------- + :class:`CRDWriter` """ return CRDWriter(filename, **kwargs) @@ -115,7 +118,7 @@ class CRDWriter(base.WriterBase): It automatically writes the CHARMM EXT extended format if there are more than 99,999 atoms. - Requires the following attributes: + Requires the following attributes to be present: - resids - resnames - names @@ -145,16 +148,27 @@ class CRDWriter(base.WriterBase): } def __init__(self, filename, **kwargs): + """ + Parameters + ---------- + filename : str or :class:`~MDAnalysis.lib.util.NamedStream` + name of the output file or a stream + """ + self.filename = util.filename(filename, ext='crd') self.crd = None def write(self, selection, frame=None): """Write selection at current trajectory frame to file. - write(selection,frame=FRAME) + Parameters + ---------- + selection : AtomGroup + group of atoms to be written + frame : int (optional) + Move the trajectory to frame `frame`; by default, write + the current frame. - selection MDAnalysis AtomGroup - frame optionally move to frame FRAME """ u = selection.universe if frame is not None: diff --git a/package/MDAnalysis/coordinates/DCD.py b/package/MDAnalysis/coordinates/DCD.py index c55aca47298..e30f52f4600 100644 --- a/package/MDAnalysis/coordinates/DCD.py +++ b/package/MDAnalysis/coordinates/DCD.py @@ -124,6 +124,7 @@ def dimensions(self): it is assumed it is a new-style CHARMM unitcell (at least since c36b2) in which box vectors were recorded. + .. warning:: The DCD format is not well defined. Check your unit cell dimensions carefully, especially when using triclinic boxes. Different software packages implement different conventions @@ -172,8 +173,57 @@ def dimensions(self, box): class DCDWriter(base.WriterBase): - """Writes to a DCD file - + """Write to a CHARMM/NAMD DCD trajectory file. + + Parameters + ---------- + filename : str + name of output file + n_atoms : int (optional) + number of atoms in dcd file + start : int (optional) + starting frame number + step : int (optional) + skip between subsequent timesteps (indicate that `step` **MD + integrator steps (!)** make up one trajectory frame); default is 1. + delta : float (optional) + timestep (**MD integrator time step (!)**, in AKMA units); default is + 20.45482949774598 (corresponding to 1 ps). + remarks : str (optional) + comments to annotate dcd file + dt : float (optional) + **Override** `step` and `delta` so that the DCD records that + `dt` ps lie between two frames. (It sets `step` = 1 and + `delta` ``= AKMA(dt)``.) The default is ``None``, in which case + `step` and `delta` are used. + convert_units : bool (optional) + units are converted to the MDAnalysis base format; ``None`` selects + the value of :data:`MDAnalysis.core.flags` ['convert_lengths']. + (see :ref:`flags-label`) + + Note + ---- + The keyword arguments set the **low-level attributes of the DCD** according + to the CHARMM format. The time between two frames would be `delta` * + `step`! For convenience, one can alternatively supply the `dt` keyword + (see above) to just tell the writer that it should record "There are `dt` + ps between each frame". + + The Writer will write the **unit cell information** to the DCD in a format + compatible with NAMD and older CHARMM versions, namely the unit cell + lengths in Angstrom and the angle cosines (see :class:`Timestep`). Newer + versions of CHARMM (at least c36b2) store the matrix of the box + vectors. Writing this matrix to a DCD is currently not supported (although + reading is supported with the :class:`DCDReader`); instead the angle + cosines are written, which *might make the DCD file unusable in CHARMM + itself*. See `Issue 187`_ for further information. + + The writing behavior of the :class:`DCDWriter` is identical to that of the + DCD molfile plugin of VMD with the exception that by default it will use + AKMA time units. + + Example + ------- Typical usage:: with DCDWriter("new.dcd", u.atoms.n_atoms) as w: @@ -182,26 +232,8 @@ class DCDWriter(base.WriterBase): Keywords are available to set some of the low-level attributes of the DCD. - :Methods: - ``d = DCDWriter(dcdfilename, n_atoms, start, step, delta, remarks)`` - - .. Note:: - - The Writer will write the **unit cell information** to the DCD in a - format compatible with NAMD and older CHARMM versions, namely the unit - cell lengths in Angstrom and the angle cosines (see - :class:`Timestep`). Newer versions of CHARMM (at least c36b2) store the - matrix of the box vectors. Writing this matrix to a DCD is currently not - supported (although reading is supported with the - :class:`DCDReader`); instead the angle cosines are written, - which *might make the DCD file unusable in CHARMM itself*. See - `Issue 187`_ for further information. - - The writing behavior of the :class:`DCDWriter` is identical to - that of the DCD molfile plugin of VMD with the exception that - by default it will use AKMA time units. - .. _Issue 187: https://github.com/MDAnalysis/mdanalysis/issues/187 + """ format = 'DCD' multiframe = True @@ -211,41 +243,6 @@ class DCDWriter(base.WriterBase): def __init__(self, filename, n_atoms, start=0, step=1, delta=mdaunits.convert(1., 'ps', 'AKMA'), dt=None, remarks="Created by DCDWriter", convert_units=None): - """Create a new DCDWriter - - :Arguments: - *filename* - name of output file - *n_atoms* - number of atoms in dcd file - *start* - starting timestep - *step* - skip between subsequent timesteps (indicate that *step* MD - integrator steps (!) make up one trajectory frame); default is 1. - *delta* - timestep (MD integrator time step (!), in AKMA units); default is - 20.45482949774598 (corresponding to 1 ps). - *remarks* - comments to annotate dcd file - *dt* - **Override** *step* and *delta* so that the DCD records that *dt* ps - lie between two frames. (It sets *step* = 1 and *delta* = ``AKMA(dt)``.) - The default is ``None``, in which case *step* and *delta* are used. - *convert_units* - units are converted to the MDAnalysis base format; ``None`` selects - the value of :data:`MDAnalysis.core.flags` ['convert_lengths']. - (see :ref:`flags-label`) - - .. Note:: - - The keyword arguments set the low-level attributes of the DCD - according to the CHARMM format. The time between two frames would be - *delta* * *step* ! For convenience, one can alternatively supply the - *dt* keyword (see above) to just tell the writer that it should - record "There are dt ps between each frame". - - """ if n_atoms == 0: raise ValueError("DCDWriter: no atoms in output trajectory") elif n_atoms is None: @@ -312,15 +309,29 @@ def _dcd_header(self): return dict(zip(desc, struct.unpack("LLiiiiidiPPiiii", self._dcd_C_str))) def write_next_timestep(self, ts=None): - ''' write a new timestep to the dcd file + """Write a new timestep to the DCD file. + + Parameters + ---------- + ts : `Timestep` (optional) + `Timestep` object containing coordinates to be written to DCD file; + by default it uses the current `Timestep` associated with the + Writer. + + Raises + ------ + :exc:`ValueError` + if wrong number of atoms supplied + :exc:`~MDAnalysis.NoDataError` + if no coordinates to be written. - *ts* - timestep object containing coordinates to be written to dcd file .. versionchanged:: 0.7.5 Raises :exc:`ValueError` instead of generic :exc:`Exception` if wrong number of atoms supplied and :exc:`~MDAnalysis.NoDataError` if no coordinates to be written. - ''' + + """ if ts is None: try: ts = self.ts @@ -391,15 +402,15 @@ class DCDReader(base.ReaderBase): ``data = dcd.correl(...)`` populate a :class:`MDAnalysis.core.Timeseries.Collection` object with computed timeseries - .. Note:: + Note + ---- + The DCD file format is not well defined. In particular, NAMD and CHARMM use + it differently. Currently, MDAnalysis tries to guess the correct format for + the unitcell representation but it can be wrong. **Check the unitcell + dimensions**, especially for triclinic unitcells (see `Issue 187`_ and + :attr:`Timestep.dimensions`). A second potential issue are the units of + time (TODO). - The DCD file format is not well defined. In particular, NAMD - and CHARMM use it differently. Currently, MDAnalysis tries to - guess the correct format for the unitcell representation but it - can be wrong. **Check the unitcell dimensions**, especially for - triclinic unitcells (see `Issue 187`_ and - :attr:`Timestep.dimensions`). A second potential issue are the - units of time (TODO). .. versionchanged:: 0.9.0 The underlying DCD reader (written in C and derived from the @@ -410,9 +421,10 @@ class DCDReader(base.ReaderBase): .. _Issue 187: https://github.com/MDAnalysis/mdanalysis/issues/187 .. versionchanged:: 0.11.0 - Frames now 0-based instead of 1-based - Native frame number read into ts._frame - Removed skip keyword and functionality + Frames now 0-based instead of 1-based. + Native frame number read into `ts._frame`. + Removed `skip` keyword and functionality. + """ format = 'DCD' flavor = 'CHARMM' @@ -516,23 +528,33 @@ def timeseries(self, asel=None, start=None, stop=None, step=None, skip=None, format='afc'): """Return a subset of coordinate data for an AtomGroup - :Arguments: - *asel* - :class:`~MDAnalysis.core.groups.AtomGroup` object - Defaults to None, in which case the full set of coordinate data - is returned. - *start*, *stop*, *step* - A range of the trajectory to access, with start being inclusive - and stop being exclusive. - *format* - the order/shape of the return data array, corresponding - to (a)tom, (f)rame, (c)oordinates all six combinations - of 'a', 'f', 'c' are allowed ie "fac" - return array - where the shape is (frame, number of atoms, - coordinates) - :Deprecated: - *skip* - Skip has been deprecated in favor of the standard keyword step. + Parameters + ---------- + asel : :class:`~MDAnalysis.core.groups.AtomGroup` + The :class:`~MDAnalysis.core.groups.AtomGroup` to read the + coordinates from. Defaults to None, in which case the full set of + coordinate data is returned. + start : int (optional) + Begin reading the trajectory at frame index `start` (where 0 is the index + of the first frame in the trajectory); the default ``None`` starts + at the beginning. + stop : int (optional) + End reading the trajectory at frame index `stop`-1, i.e, `stop` is excluded. + The trajectory is read to the end with the default ``None``. + step : int (optional) + Step size for reading; the default ``None`` is equivalent to 1 and means to + read every frame. + format : str (optional) + the order/shape of the return data array, corresponding + to (a)tom, (f)rame, (c)oordinates all six combinations + of 'a', 'f', 'c' are allowed ie "fac" - return array + where the shape is (frame, number of atoms, + coordinates) + + + .. deprecated:: 0.16.0 + `skip` has been deprecated in favor of the standard keyword `step`. + """ if skip is not None: step = skip @@ -557,17 +579,37 @@ def timeseries(self, asel=None, start=None, stop=None, step=None, skip=None, return self._read_timeseries(atom_numbers, start, stop, step, format) def correl(self, timeseries, start=None, stop=None, step=None, skip=None): - """Populate a TimeseriesCollection object with timeseries computed from the trajectory - - :Arguments: - *timeseries* - :class:`MDAnalysis.core.Timeseries.TimeseriesCollection` - *start, stop, step* - A subset of the trajectory to use, with start being inclusive - and stop being exclusive. - :Deprecated: - *skip* - Skip has been deprecated in favor of the standard keyword step. + """Populate a :class:`~MDAnalysis.core.Timeseries.TimeseriesCollection` object + with time series computed from the trajectory. + + Calling this method will iterate through the whole trajectory and + perform the calculations prescribed in `timeseries`. + + Parameters + ---------- + timeseries : :class:`MDAnalysis.core.Timeseries.TimeseriesCollection` + The :class:`MDAnalysis.core.Timeseries.TimeseriesCollection` that defines what kind + of computations should be performed on the data in this trajectory. + start : int (optional) + Begin reading the trajectory at frame index `start` (where 0 is the index + of the first frame in the trajectory); the default ``None`` starts + at the beginning. + stop : int (optional) + End reading the trajectory at frame index `stop`-1, i.e, `stop` is excluded. + The trajectory is read to the end with the default ``None``. + step : int (optional) + Step size for reading; the default ``None`` is equivalent to 1 and means to + read every frame. + + Note + ---- + The `correl` functionality is only implemented for DCD trajectories and + the :class:`DCDReader`. + + + .. deprecated:: 0.16.0 + `skip` has been deprecated in favor of the standard keyword `step`. + """ if skip is not None: step = skip @@ -592,40 +634,53 @@ def close(self): self.dcdfile = None def Writer(self, filename, **kwargs): - """Returns a DCDWriter for *filename* with the same parameters as this DCD. - - All values can be changed through keyword arguments. - - :Arguments: - *filename* - filename of the output DCD trajectory - :Keywords: - *n_atoms* - number of atoms - *start* - number of the first recorded MD step - *step* - indicate that *step* MD steps (!) make up one trajectory frame - *delta* - MD integrator time step (!), in AKMA units - *dt* - **Override** *step* and *delta* so that the DCD records that *dt* ps - lie between two frames. (It sets *step* = 1 and *delta* = ``AKMA(dt)``.) - The default is ``None``, in which case *step* and *delta* are used. - *remarks* - string that is stored in the DCD header [XXX -- max length?] - - :Returns: :class:`DCDWriter` - - .. Note:: - - The keyword arguments set the low-level attributes of the DCD - according to the CHARMM format. The time between two frames would be - *delta* * *step* ! + """Returns a DCDWriter for `filename` with the same parameters as this DCD. + + Defaults for all values are obtained from the `DCDReader` itself but + all values can be changed through keyword arguments. + + Parameters + ---------- + filename : str + filename of the output DCD trajectory + n_atoms : int (optional) + number of atoms + start : int (optional) + number of the first recorded MD step + step : int (optional) + indicate that `step` **MD steps (!)** make up one trajectory frame + delta : float (optional) + **MD integrator time step (!)**, in AKMA units + dt : float (optional) + **Override** `step` and `delta` so that the DCD records that + `dt` ps lie between two frames. (It sets `step` `` = 1`` and + `delta` `` = AKMA(dt)``.) The default is ``None``, in which case + `step` and `delta` are used. + + remarks : str (optional) + string that is stored in the DCD header + + Returns + ------- + :class:`DCDWriter` + + + Note + ---- + The keyword arguments set the low-level attributes of the DCD according + to the CHARMM format. The time between two frames would be `delta` * + `step`! + + Here `step` is really the number of MD integrator time steps that + occured after this frame, including the frame itself that is the + coordinate snapshot and `delta` is the integrator stime step. The DCD + file format contains this information so it needs to be provided here. + See Also -------- :class:`DCDWriter` + """ n_atoms = kwargs.pop('n_atoms', self.n_atoms) kwargs.setdefault('start', self.start_timestep) diff --git a/package/MDAnalysis/coordinates/GMS.py b/package/MDAnalysis/coordinates/GMS.py index 9e4762c4ce2..840d2588bb4 100644 --- a/package/MDAnalysis/coordinates/GMS.py +++ b/package/MDAnalysis/coordinates/GMS.py @@ -30,7 +30,11 @@ Current version was approbated with US-GAMESS & Firefly only. There appears to be no rigid format definition so it is likely users -will need to tweak this Class. +will need to tweak the :class:`GMSReader`. + +.. autoclass:: GMSReader + :members: + """ from __future__ import absolute_import @@ -55,13 +59,17 @@ class GMSReader(base.ReaderBase): ``for ts in out:`` iterate through trajectory - .. Note: this can read both compressed (foo.out) and compressed - (foo.out.bz2 or foo.out.gz) files; uncompression is handled - on the fly + Note + ---- + :class:`GMSReader` can read both uncompressed (``foo.out``) and + compressed (``foo.out.bz2`` or ``foo.out.gz``) files; + decompression is handled on the fly + .. versionchanged:: 0.11.0 - Frames now 0-based instead of 1-based - Added dt and time_offset keywords (passed to Timestep) + Frames now 0-based instead of 1-based. + Added `dt` and `time_offset` keywords (passed to :class:`Timestep`). + """ format = "GMS" @@ -171,7 +179,7 @@ def _read_frame(self, frame): self.outfile.seek(self._offsets[frame]) self.ts.frame = frame - 1 # gets +1'd in _read_next return self._read_next_timestep() - + def _read_next_timestep(self, ts=None): # check that the timestep object exists if ts is None: diff --git a/package/MDAnalysis/coordinates/GRO.py b/package/MDAnalysis/coordinates/GRO.py index 302b15a0e41..3a36fa69d2f 100644 --- a/package/MDAnalysis/coordinates/GRO.py +++ b/package/MDAnalysis/coordinates/GRO.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -27,30 +27,50 @@ Classes to read and write Gromacs_ GRO_ coordinate files; see the notes on the `GRO format`_ which includes a conversion routine for the box. -GROWriter format strings ------------------------- -The GROWriter class has a .fmt attribute, which is a dictionary of different -strings for writing lines in .gro files. These are as follows: +Classes +------- -n_atoms +.. autoclass:: Timestep + :members: + +.. autoclass:: GROReader + :members: + +.. autoclass:: GROWriter + :members: + + +Developer notes: ``GROWriter`` format strings +--------------------------------------------- + +The :class:`GROWriter` class has a :attr:`GROWriter.fmt` attribute, which is a dictionary of different +strings for writing lines in ``.gro`` files. These are as follows: + +``n_atoms`` For the first line of the gro file, supply the number of atoms in the system. - Eg: fmt['n_atoms'].format(42) + E.g.:: -xyz + fmt['n_atoms'].format(42) + +``xyz`` An atom line without velocities. Requires that the 'resid', 'resname', 'name', 'index' and 'pos' keys be supplied. - Eg: fmt['xyz'].format(resid=1, resname='SOL', name='OW2', index=2, pos=(0.0, 1.0, 2.0)) + E.g.:: + + fmt['xyz'].format(resid=1, resname='SOL', name='OW2', index=2, pos=(0.0, 1.0, 2.0)) -xyz_v +``xyz_v`` As above, but with velocities. Needs an additional keyword 'vel'. -box_orthorhombic +``box_orthorhombic`` The final line of the gro file which gives box dimensions. Requires the box keyword to be given, which should be the three cartesian dimensions. - Eg: fmt['box_orthorhombic'].format(box=(10.0, 10.0, 10.0)) + E.g.:: + + fmt['box_orthorhombic'].format(box=(10.0, 10.0, 10.0)) -box_triclinic +``box_triclinic`` As above, but for a non orthorhombic box. Requires the box keyword, but this time as a length 9 vector. This is a flattened version of the (3,3) triclinic vector representation of the unit cell. The rearrangement into the odd @@ -60,6 +80,7 @@ .. _Gromacs: http://www.gromacs.org .. _GRO: http://manual.gromacs.org/current/online/gro.html .. _GRO format: http://chembytes.wikidot.com/g-grofile + """ from __future__ import absolute_import @@ -121,7 +142,7 @@ def dimensions(self, box): class GROReader(base.SingleFrameReaderBase): """Reader for the Gromacs GRO structure format. - + .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based """ @@ -190,11 +211,14 @@ def _read_first_frame(self): def Writer(self, filename, n_atoms=None, **kwargs): """Returns a CRDWriter for *filename*. - :Arguments: - *filename* + Parameters + ---------- + filename: str filename of the output GRO file - :Returns: :class:`GROWriter` + Returns + ------- + :class:`GROWriter` """ if n_atoms is None: @@ -210,18 +234,19 @@ class GROWriter(base.WriterBase): - resnames (defaults to 'UNK') - resids (defaults to '1') - .. Note:: + Note + ---- + The precision is hard coded to three decimal places - The precision is hard coded to three decimal places .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based .. versionchanged:: 0.13.0 - Now strictly writes positions with 3dp precision - and velocities with 4dp + Now strictly writes positions with 3dp precision. + and velocities with 4dp. Removed the `convert_dimensions_to_unitcell` method, - use `Timestep.triclinic_dimensions` instead - Now now writes velocities where possible + use `Timestep.triclinic_dimensions` instead. + Now now writes velocities where possible. """ format = 'GRO' @@ -251,6 +276,9 @@ def __init__(self, filename, convert_units=None, n_atoms=None, **kwargs): n_atoms : int (optional) number of atoms + convert_units : str (optional) + units are converted to the MDAnalysis base format; ``None`` selects + the value of :data:`MDAnalysis.core.flags` ['convert_lengths'] """ self.filename = util.filename(filename, ext='gro') self.n_atoms = n_atoms @@ -264,19 +292,19 @@ def write(self, obj): Parameters ----------- - obj : AtomGroup / Universe / Timestep + obj : AtomGroup or Universe or :class:`Timestep` Note ---- - The GRO format only allows 5 digits for resid and atom - number. If these number become larger than 99,999 then this + The GRO format only allows 5 digits for *resid* and *atom + number*. If these numbers become larger than 99,999 then this routine will chop off the leading digits. .. versionchanged:: 0.7.6 - resName and atomName are truncated to a maximum of 5 characters + *resName* and *atomName* are truncated to a maximum of 5 characters .. versionchanged:: 0.16.0 - frame kwarg has been removed + `frame` kwarg has been removed """ # write() method that complies with the Trajectory API diff --git a/package/MDAnalysis/coordinates/INPCRD.py b/package/MDAnalysis/coordinates/INPCRD.py index 90a0e03e0f2..96b14bd653b 100644 --- a/package/MDAnalysis/coordinates/INPCRD.py +++ b/package/MDAnalysis/coordinates/INPCRD.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -24,10 +24,17 @@ """INPCRD structure files in MDAnalysis --- :mod:`MDAnalysis.coordinates.INPCRD` ================================================================================ -Read and write coordinates in Amber_ coordinate/restart file (suffix -"inpcrd"). +Read coordinates in Amber_ coordinate/restart file (suffix "inpcrd"). .. _Amber: http://ambermd.org/formats.html#restart + + +Classes +------- + +.. autoclass:: INPReader + :members: + """ from __future__ import absolute_import, division, print_function, unicode_literals @@ -36,6 +43,8 @@ from . import base class INPReader(base.SingleFrameReaderBase): + """Reader for Amber restart files.""" + format = ['INPCRD', 'RESTRT'] units = {'length': 'Angstrom'} @@ -61,7 +70,7 @@ def _read_first_frame(self): 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 + # Read last coordinate if necessary if self.n_atoms % 2: line = inf.readline() for i in range(3): diff --git a/package/MDAnalysis/coordinates/LAMMPS.py b/package/MDAnalysis/coordinates/LAMMPS.py index afb62f42538..6ffd9da5a38 100644 --- a/package/MDAnalysis/coordinates/LAMMPS.py +++ b/package/MDAnalysis/coordinates/LAMMPS.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -45,7 +45,8 @@ :class:`~MDAnalysis.core.universe.Universe` (which then calls :class:`DCDReader`). -.. Rubric:: Example: Loading a LAMMPS simulation +Example: Loading a LAMMPS simulation +------------------------------------ To load a LAMMPS simulation from a LAMMPS data file (using the :class:`~MDAnalysis.topology.LAMMPSParser.DATAParser`) together with a @@ -70,10 +71,9 @@ Note ---- - - Lennard-Jones units are not implemented. See :mod:`MDAnalysis.units` for - other recognized values and the documentation for the LAMMPS `units - command`_. +Lennard-Jones units are not implemented. See :mod:`MDAnalysis.units` +for other recognized values and the documentation for the LAMMPS +`units command`_. See Also -------- @@ -104,6 +104,7 @@ .. autoclass:: DATAWriter :members: :inherited-members: + """ from __future__ import absolute_import @@ -249,7 +250,7 @@ def __init__(self, filename, convert_units=None, **kwargs): 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['velocity'] = kwargs.pop('velocityunit', self.units['length']+'/'+self.units['time']) def _write_atoms(self, atoms): @@ -344,11 +345,13 @@ def _write_dimensions(self, dimensions): @requires('types', 'masses') def write(self, selection, frame=None): - """Write selection at current trajectory frame to file, including - sections Atoms, Masses, Velocities, Bonds, Angles, Dihedrals, and - Impropers (if these are defined). Atoms section is written in the - "full" sub-style if charges are available or "molecular" sub-style if - they are not. Molecule id in atoms section is set to to 0. + """Write selection at current trajectory frame to file. + + The sections for Atoms, Masses, Velocities, Bonds, Angles, + Dihedrals, and Impropers (if these are defined) are + written. The Atoms section is written in the "full" sub-style + if charges are available or "molecular" sub-style if they are + not. Molecule id in atoms section is set to to 0. No other sections are written to the DATA file. As of this writing, other sections are not parsed into the topology @@ -356,15 +359,17 @@ def write(self, selection, frame=None): Note ---- - If the selection includes a partial fragment, then only the bonds, angles, - etc. whose atoms are contained within the selection will be included. + If the selection includes a partial fragment, then only the bonds, + angles, etc. whose atoms are contained within the selection will be + included. Parameters ---------- - selection : AtomGroup + selection : AtomGroup or Universe MDAnalysis AtomGroup (selection or Universe.atoms) or also Universe - frame : Optional[int] - optionally move to frame number *frame* + frame : int (optional) + optionally move to frame number `frame` + """ u = selection.universe if frame is not None: diff --git a/package/MDAnalysis/coordinates/MMTF.py b/package/MDAnalysis/coordinates/MMTF.py index 87ad92fcc7e..7c2d7293b2d 100644 --- a/package/MDAnalysis/coordinates/MMTF.py +++ b/package/MDAnalysis/coordinates/MMTF.py @@ -54,9 +54,7 @@ def _parse_mmtf(fn): class MMTFReader(base.SingleFrameReaderBase): - """Topology parser for the Macromolecular Transmission Format format (MMTF_). - - """ + """Coordinate reader for the Macromolecular Transmission Format format (MMTF_).""" format = 'MMTF' def _read_first_frame(self): @@ -88,7 +86,8 @@ def fetch_mmtf(pdb_id): Returns ------- - MDAnalysis Universe of the corresponding PDB system + Universe + MDAnalysis Universe of the corresponding PDB system See Also diff --git a/package/MDAnalysis/coordinates/MOL2.py b/package/MDAnalysis/coordinates/MOL2.py index 150183011fe..0903c79c0d5 100644 --- a/package/MDAnalysis/coordinates/MOL2.py +++ b/package/MDAnalysis/coordinates/MOL2.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -20,20 +20,19 @@ # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # -""" -MOL2 file format --- :mod:`MDAnalysis.coordinates.MOL2` +"""MOL2 file format --- :mod:`MDAnalysis.coordinates.MOL2` ======================================================== -Classes to read Tripos_ molecule structure format (MOL2_) -coordinate and topology files. Used by the DOCK_ docking -code. +Classes to work with Tripos_ molecule structure format (MOL2_) coordinate and +topology files. Used, for instance, by the DOCK_ docking code. + -Examples -~~~~~~~~ +Example for working with mol2 files +----------------------------------- To open a mol2, remove all hydrogens and save as a new file, use the following:: - u = Universe("MDAnalysis/testsuite/MDAnalysisTests/data/mol2/Molecule.mol2") + u = Universe("Molecule.mol2") gr = u.select_atoms("not name H*") print(len(u.atoms), len(gr)) gr.write("Molecule_noh.mol2") @@ -41,6 +40,75 @@ .. _MOL2: http://www.tripos.com/data/support/mol2.pdf .. _Tripos: http://www.tripos.com/ .. _DOCK: http://dock.compbio.ucsf.edu/ + + +See Also +-------- +rdkit: rdkit_ is an open source cheminformatics toolkit with more mol2 + functionality + +.. _rdkit: http://www.rdkit.org/docs/GettingStartedInPython.html + + +Classes +------- + +.. autoclass:: MOL2Reader + :members: + +.. autoclass:: MOL2Writer + :members: + + +MOL2 format notes +----------------- + +* MOL2 Format Specification: (http://www.tripos.com/data/support/mol2.pdf) +* Example file (http://www.tripos.com/mol2/mol2_format3.html):: + + # Name: benzene + # Creating user name: tom + # Creation time: Wed Dec 28 00:18:30 1988 + + # Modifying user name: tom + # Modification time: Wed Dec 28 00:18:30 1988 + + @MOLECULE + benzene + 12 12 1 0 0 + SMALL + NO_CHARGES + + + @ATOM + 1 C1 1.207 2.091 0.000 C.ar 1 BENZENE 0.000 + 2 C2 2.414 1.394 0.000 C.ar 1 BENZENE 0.000 + 3 C3 2.414 0.000 0.000 C.ar 1 BENZENE 0.000 + 4 C4 1.207 -0.697 0.000 C.ar 1 BENZENE 0.000 + 5 C5 0.000 0.000 0.000 C.ar 1 BENZENE 0.000 + 6 C6 0.000 1.394 0.000 C.ar 1 BENZENE 0.000 + 7 H1 1.207 3.175 0.000 H 1 BENZENE 0.000 + 8 H2 3.353 1.936 0.000 H 1 BENZENE 0.000 + 9 H3 3.353 -0.542 0.000 H 1 BENZENE 0.000 + 10 H4 1.207 -1.781 0.000 H 1 BENZENE 0.000 + 11 H5 -0.939 -0.542 0.000 H 1 BENZENE 0.000 + 12 H6 -0.939 1.936 0.000 H 1 BENZENE 0.000 + @BOND + 1 1 2 ar + 2 1 6 ar + 3 2 3 ar + 4 3 4 ar + 5 4 5 ar + 6 5 6 ar + 7 1 7 1 + 8 2 8 1 + 9 3 9 1 + 10 4 10 1 + 11 5 11 1 + 12 6 12 1 + @SUBSTRUCTURE + 1 BENZENE 1 PERM 0 **** **** 0 ROOT + """ from __future__ import absolute_import @@ -55,15 +123,22 @@ class MOL2Reader(base.ReaderBase): """Reader for MOL2 structure format. .. versionchanged:: 0.11.0 - Frames now 0-based instead of 1-based - MOL2 now resuses the same Timestep object for every frame - previously created a new instance of Timestep each frame + Frames now 0-based instead of 1-based. + MOL2 now reuses the same Timestep object for every frame, + previously created a new instance of Timestep each frame. """ format = 'MOL2' units = {'time': None, 'length': 'Angstrom'} def __init__(self, filename, **kwargs): - """Read coordinates from *filename*.""" + """Read coordinates from `filename`. + + + Parameters + ---------- + filename : str or NamedStream + name of the mol2 file or stream + """ super(MOL2Reader, self).__init__(filename, **kwargs) self.n_atoms = None @@ -166,16 +241,18 @@ def _reopen(self): class MOL2Writer(base.WriterBase): - """ + """mol2 format writer + + Write a file in the Tripos_ molecule structure format (MOL2_). - MOL2Writer Limitations - ---------------------- - MOL2Writer can only be used to write out previously loaded MOL2 files. + Note + ---- + :class:`MOL2Writer` can only be used to write out previously loaded MOL2 files. If you're trying to convert, for example, a PDB file to MOL you should - use other tools, like rdkit (http://www.rdkit.org/docs/GettingStartedInPython.html). + use other tools, like rdkit_. + + Here is an example how to use rdkit_ to convert a PDB to MOL:: - Here is an example how to use rdkit to convert a PDB to MOL:: - from rdkit import Chem mol = Chem.MolFromPDBFile("molecule.pdb", removeHs=False) Chem.MolToMolFile(mol, "molecule.mol" ) @@ -185,51 +262,8 @@ class MOL2Writer(base.WriterBase): See page 7 for list of SYBYL atomtypes (http://tripos.com/tripos_resources/fileroot/pdfs/mol2_format2.pdf). - * MOL2 Format Specification: (http://www.tripos.com/data/support/mol2.pdf) - * Example file (http://www.tripos.com/mol2/mol2_format3.html):: - - # Name: benzene - # Creating user name: tom - # Creation time: Wed Dec 28 00:18:30 1988 - - # Modifying user name: tom - # Modification time: Wed Dec 28 00:18:30 1988 - - @MOLECULE - benzene - 12 12 1 0 0 - SMALL - NO_CHARGES - - - @ATOM - 1 C1 1.207 2.091 0.000 C.ar 1 BENZENE 0.000 - 2 C2 2.414 1.394 0.000 C.ar 1 BENZENE 0.000 - 3 C3 2.414 0.000 0.000 C.ar 1 BENZENE 0.000 - 4 C4 1.207 -0.697 0.000 C.ar 1 BENZENE 0.000 - 5 C5 0.000 0.000 0.000 C.ar 1 BENZENE 0.000 - 6 C6 0.000 1.394 0.000 C.ar 1 BENZENE 0.000 - 7 H1 1.207 3.175 0.000 H 1 BENZENE 0.000 - 8 H2 3.353 1.936 0.000 H 1 BENZENE 0.000 - 9 H3 3.353 -0.542 0.000 H 1 BENZENE 0.000 - 10 H4 1.207 -1.781 0.000 H 1 BENZENE 0.000 - 11 H5 -0.939 -0.542 0.000 H 1 BENZENE 0.000 - 12 H6 -0.939 1.936 0.000 H 1 BENZENE 0.000 - @BOND - 1 1 2 ar - 2 1 6 ar - 3 2 3 ar - 4 3 4 ar - 5 4 5 ar - 6 5 6 ar - 7 1 7 1 - 8 2 8 1 - 9 3 9 1 - 10 4 10 1 - 11 5 11 1 - 12 6 12 1 - @SUBSTRUCTURE - 1 BENZENE 1 PERM 0 **** **** 0 ROOT + + .. _rdkit: http://www.rdkit.org/docs/GettingStartedInPython.html .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based @@ -239,16 +273,16 @@ class MOL2Writer(base.WriterBase): multiframe = True units = {'time': None, 'length': 'Angstrom'} - def __init__(self, filename, n_atoms=None, - convert_units=None): + def __init__(self, filename, n_atoms=None, convert_units=None): """Create a new MOL2Writer - :Arguments: - *filename* - name of output file - *convert_units* - units are converted to the MDAnalysis base format; ``None`` selects - the value of :data:`MDAnalysis.core.flags` ['convert_lengths'] + Parameters + ---------- + filename: str + name of output file + convert_units: bool (optional) + units are converted to the MDAnalysis base format; ``None`` selects + the value of :data:`MDAnalysis.core.flags` ['convert_lengths'] """ self.filename = filename if convert_units is None: diff --git a/package/MDAnalysis/coordinates/PDB.py b/package/MDAnalysis/coordinates/PDB.py index 471136ef2ee..344c2c45e38 100644 --- a/package/MDAnalysis/coordinates/PDB.py +++ b/package/MDAnalysis/coordinates/PDB.py @@ -49,31 +49,22 @@ trajectory, while writing each frame:: calphas = universe.select_atoms("name CA") - W = MDAnalysis.Writer("calpha_traj.pdb", multiframe=True) - for ts in u.trajectory: - W.write(calphas) - W.close() + with MDAnalysis.Writer("calpha_traj.pdb", multiframe=True) as W: + for ts in u.trajectory: + W.write(calphas) It is important to *always close the trajectory* when done because only at this step is the final END_ record written, which is required by the `PDB 3.2 -standard`_. +standard`_. Using the writer as a context manager ensures that this always +happens. -Implementations ---------------- +Capabilities +------------ -PDB I/O is available in the form of the Simple PDB Reader/Writers. - -..deprecated:: 0.15.0 -Readers and writers solely available in the form of -Simple Readers and Writers, see below. - -Simple PDB Reader and Writer ------------------------------------------ A pure-Python implementation for PDB files commonly encountered in MD -simulations comes under the names :class:`PDBReader` and -:class:`PDBWriter`. It only implements a subset of the `PDB 3.2 standard`_ -(for instance, it does not deal with insertion codes) and also allows some +simulations comes under the names :class:`PDBReader` and :class:`PDBWriter`. It +only implements a subset of the `PDB 3.2 standard`_ and also allows some typical enhancements such as 4-letter resids (introduced by CHARMM/NAMD). The :class:`PDBReader` can read multi-frame PDB files and represents @@ -83,26 +74,11 @@ to write a PDB trajectory by default (equivalent to using *multiframe* = ``True``). -Examples -~~~~~~~~ - -In order to write a **multi-frame PDB trajectory** from a universe *u* one can -do the following:: - - pdb = MDAnalysis.Writer("all.pdb", multiframe=True) - for ts in u.trajectory: - pdb.write(u) - pdb.close() -Similarly, writing only a protein:: +Examples for working with PDB files +----------------------------------- - pdb = MDAnalysis.Writer("protein.pdb", multiframe=True) - protein = u.select_atoms("protein") - for ts in u.trajectory: - pdb.write(protein) - pdb.close() - -A single frame can be written with the +A **single frame PDB** can be written with the :meth:`~MDAnalysis.core.groups.AtomGroup.write` method of any :class:`~MDAnalysis.core.groups.AtomGroup`:: @@ -112,14 +88,33 @@ Alternatively, get the single frame writer and supply the :class:`~MDAnalysis.core.groups.AtomGroup`:: - pdb = MDAnalysis.Writer("protein.pdb") protein = u.select_atoms("protein") - pdb.write(protein) - pdb.close() + with MDAnalysis.Writer("protein.pdb") as pdb: + pdb.write(protein) + +In order to write a **multi-frame PDB trajectory** from a universe *u* one can +do the following:: + + with MDAnalysis.Writer("all.pdb", multiframe=True) as pdb: + for ts in u.trajectory: + pdb.write(u) + +Similarly, writing only a protein:: + + protein = u.select_atoms("protein") + with MDAnalysis.Writer("protein.pdb", multiframe=True) as pdb: + for ts in u.trajectory: + pdb.write(protein) + Classes -~~~~~~~ +------- + +.. versionchanged:: 0.16.0 + PDB readers and writers based on :class:`Bio.PDB.PDBParser` were retired and + removed. + .. autoclass:: PDBReader :members: @@ -139,13 +134,10 @@ :members: :inherited-members: -..deprecated:: 0.15.0 - The "permissive" flag is not used anymore (and effectively defaults to True); - it will be completely removed in 0.16.0. - .. _`PDB 3.2 standard`: http://www.wwpdb.org/documentation/format32/v3.2.html + """ from __future__ import absolute_import @@ -326,11 +318,14 @@ def __init__(self, filename, **kwargs): def Writer(self, filename, **kwargs): """Returns a PDBWriter for *filename*. - :Arguments: - *filename* - filename of the output PDB file + Parameters + ---------- + filename : str + filename of the output PDB file - :Returns: :class:`PDBWriter` + Returns + ------- + :class:`PDBWriter` """ kwargs.setdefault('multiframe', self.n_frames > 1) @@ -423,11 +418,12 @@ class PDBWriter(base.WriterBase): .. _ENDMDL: http://www.wwpdb.org/documentation/format32/sect9.html#ENDMDL .. _CONECT: http://www.wwpdb.org/documentation/format32/sect10.html#CONECT + Note ---- This class is identical to :class:`MultiPDBWriter` with the one exception that it defaults to writing single-frame PDB files as if - *multiframe* = ``False`` was selected. + `multiframe` = ``False`` was selected. .. versionchanged:: 0.7.5 @@ -531,7 +527,6 @@ def __init__(self, filename, bonds="conect", n_atoms=None, start=0, step=1, multi frame PDB file in which frames are written as MODEL_ ... ENDMDL_ records. If ``None``, then the class default is chosen. [``None``] - Note ---- Writing bonds currently only works when writing a whole @@ -729,10 +724,11 @@ def write(self, obj): used as the PDB chainID (but see :meth:`~PDBWriter.ATOM` for details). - :Arguments: - *obj* - :class:`~MDAnalysis.core.groups.AtomGroup` or - :class:`~MDAnalysis.core.universe.Universe` + Parameters + ---------- + obj + The :class:`~MDAnalysis.core.groups.AtomGroup` or + :class:`~MDAnalysis.core.universe.Universe` to write. """ self._update_frame(obj) diff --git a/package/MDAnalysis/coordinates/PDBQT.py b/package/MDAnalysis/coordinates/PDBQT.py index 2e0a40ba18d..45127e858d8 100644 --- a/package/MDAnalysis/coordinates/PDBQT.py +++ b/package/MDAnalysis/coordinates/PDBQT.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -55,7 +55,7 @@ class PDBQTReader(base.SingleFrameReaderBase): - CRYST1 for unitcell A,B,C, alpha,beta,gamm - ATOM. HETATM for x,y,z - Original `PDB format documentation`_ with `AutoDOCK extensions`_ + Original `PDB format documentation`_ with `AutoDOCK extensions`_ .. _PDB format documentation: @@ -221,14 +221,13 @@ def close(self): def write(self, selection, frame=None): """Write selection at current trajectory frame to file. - write(selection, frame=FRAME) - Parameters ---------- selection : AtomGroup The selection to be written - frame : int, optional - optionally move to *frame* before writing + frame : int (optional) + optionally move to frame index `frame` before writing; the default + is to write the current trajectory frame Note ---- @@ -239,6 +238,7 @@ def write(self, selection, frame=None): .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based + """ u = selection.universe if frame is not None: diff --git a/package/MDAnalysis/coordinates/PQR.py b/package/MDAnalysis/coordinates/PQR.py index 181ef6272fa..d51142a3f7e 100644 --- a/package/MDAnalysis/coordinates/PQR.py +++ b/package/MDAnalysis/coordinates/PQR.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -143,11 +143,14 @@ def _read_first_frame(self): def Writer(self, filename, **kwargs): """Returns a PQRWriter for *filename*. - :Arguments: - *filename* - filename of the output PQR file + Parameters + ---------- + filename : str + filename of the output PQR file - :Returns: :class:`PQRWriter` + Returns + ------- + :class:`PQRWriter` """ return PQRWriter(filename, **kwargs) @@ -185,7 +188,7 @@ def __init__(self, filename, convert_units=None, **kwargs): ---------- filename : str output filename - remarks : str, optionak + remarks : str (optional) remark lines (list of strings) or single string to be added to the top of the PQR file """ @@ -204,12 +207,14 @@ def write(self, selection, frame=None): ---------- selection : AtomGroup or Universe MDAnalysis AtomGroup or Universe - frame : int, optional - optionally move to frame number *frame* + frame : int (optional) + optionally move to frame index `frame`; by default, write the + current frame .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based + """ # write() method that complies with the Trajectory API u = selection.universe diff --git a/package/MDAnalysis/coordinates/TRJ.py b/package/MDAnalysis/coordinates/TRJ.py index d484671795d..9e7eea6947c 100644 --- a/package/MDAnalysis/coordinates/TRJ.py +++ b/package/MDAnalysis/coordinates/TRJ.py @@ -19,26 +19,28 @@ # MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # -""" -AMBER trajectories --- :mod:`MDAnalysis.coordinates.TRJ` +"""AMBER trajectories --- :mod:`MDAnalysis.coordinates.TRJ` ======================================================== AMBER_ can write :ref:`ASCII trajectories` ("traj") and :ref:`binary trajectories` ("netcdf"). MDAnalysis supports reading of both formats and writing for the binary trajectories. -.. Note:: +Note +---- +Support for AMBER is still somewhat *experimental* and feedback and +contributions are highly appreciated. Use the `Issue Tracker`_ or get in touch +on the `MDAnalysis mailinglist`_. - Support for AMBER is *experimental* and feedback and contributions - are highly appreciated. Use the `Issue Tracker`_ or get in touch on - the `MDAnalysis mailinglist`_. .. rubric:: Units +AMBER trajectories are assumed to be in the following units: + * lengths in Angstrom (Å) * time in ps (but see below) -AMBER trajectory coordinate frames are based on a :class:`Timestep` +AMBER trajectory coordinate frames are based on a custom :class:`Timestep` object. .. autoclass:: Timestep @@ -127,8 +129,6 @@ .. _Issue Tracker: https://github.com/MDAnalysis/mdanalysis/issues .. _MDAnalysis mailinglist: http://groups.google.com/group/mdnalysis-discussion - - """ from __future__ import (absolute_import, division, print_function, unicode_literals) @@ -161,8 +161,8 @@ class Timestep(base.Timestep): """AMBER trajectory Timestep. - The Timestep can be initialized with *arg* being an integer - (the number of atoms) and an optional keyword argument *velocities* to + The Timestep can be initialized with `arg` being an integer + (the number of atoms) and an optional keyword argument `velocities` to allocate space for both coordinates and velocities; .. versionchanged:: 0.10.0 @@ -192,8 +192,8 @@ class TRJReader(base.ReaderBase): .. _AMBER TRJ format: http://ambermd.org/formats.html#trajectory .. versionchanged:: 0.11.0 - Frames now 0-based instead of 1-based - kwarg 'delta' renamed to 'dt', for uniformity with other Readers + Frames now 0-based instead of 1-based. + kwarg `delta` renamed to `dt`, for uniformity with other Readers """ format = ['TRJ', 'MDCRD', 'CRDBOX'] units = {'time': 'ps', 'length': 'Angstrom'} @@ -293,7 +293,8 @@ def _detect_amber_box(self): - this WILL fail if we have exactly 1 atom in the trajectory because there's no way to distinguish the coordinates from the box so for 1 atom we always assume no box - XXX: needs a Timestep that knows about AMBER unitcells! + + .. TODO:: needs a Timestep that knows about AMBER unitcells! """ if self.n_atoms == 1: # for 1 atom we cannot detect the box with the current approach @@ -385,7 +386,7 @@ class NCDFReader(base.ReaderBase): AMBER binary trajectories are automatically recognised by the file extension ".ncdf". - The number of atoms (*n_atoms*) does not have to be provided as it can + The number of atoms (`n_atoms`) does not have to be provided as it can be read from the trajectory. The trajectory reader can randomly access frames and therefore supports direct indexing (with 0-based frame indices) and full-feature trajectory iteration, including slicing. @@ -412,12 +413,13 @@ class NCDFReader(base.ReaderBase): -------- :class:`NCDFWriter` + .. versionadded: 0.7.6 .. versionchanged:: 0.10.0 Added ability to read Forces .. versionchanged:: 0.11.0 - Frame labels now 0-based instead of 1-based - kwarg 'delta' renamed to 'dt', for uniformity with other Readers + Frame labels now 0-based instead of 1-based. + kwarg `delta` renamed to `dt`, for uniformity with other Readers. """ format = ['NCDF', 'NC'] @@ -568,22 +570,24 @@ def close(self): self.trjfile = None def Writer(self, filename, **kwargs): - """Returns a NCDFWriter for *filename* with the same parameters as this NCDF. + """Returns a NCDFWriter for `filename` with the same parameters as this NCDF. All values can be changed through keyword arguments. - :Arguments: - *filename* - filename of the output NCDF trajectory - :Keywords: - *n_atoms* - number of atoms - *dt* - length of one timestep in picoseconds - *remarks* - string that is stored in the title field - - :Returns: :class:`NCDFWriter` + Parameters + ---------- + filename : str + filename of the output NCDF trajectory + n_atoms : int (optional) + number of atoms + dt : float (optional) + length of one timestep in picoseconds + remarks : str (optional) + string that is stored in the title field + + Returns + ------- + :class:`NCDFWriter` """ n_atoms = kwargs.pop('n_atoms', self.n_atoms) kwargs.setdefault('remarks', self.remarks) @@ -610,12 +614,13 @@ class NCDFWriter(base.WriterBase): -------- :class:`NCDFReader` + .. versionadded: 0.7.6 .. versionchanged:: 0.10.0 Added ability to write velocities and forces .. versionchanged:: 0.11.0 - kwarg 'delta' renamed to 'dt', for uniformity with other Readers + kwarg `delta` renamed to `dt`, for uniformity with other Readers """ format = 'NCDF' @@ -639,30 +644,29 @@ def __init__(self, **kwargs): """Create a new NCDFWriter - :Arguments: - *filename* + Parameters + ---------- + filename : str name of output file - *n_atoms* + n_atoms : int number of atoms in trajectory file - - :Keywords: - *start* + start : int (optional) starting timestep - *step* + step : int (optional) skip between subsequent timesteps - *dt* + dt : float (optional) timestep - *convert_units* + convert_units : bool (optional) ``True``: units are converted to the AMBER base format; ``None`` selects the value of :data:`MDAnalysis.core.flags` ['convert_lengths'] (see :ref:`flags-label`). - *zlib* + zlib : bool (optional) compress data [``False``] - *cmplevel* + cmplevel : int (optional) compression level (1-9) [1] - *velocities* + velocities : bool (optional) Write velocities into the trajectory [``False``] - *forces* + forces : bool (optional) Write forces into the trajectory [``False``] """ self.filename = filename @@ -806,18 +810,33 @@ def _init_netcdf(self, periodic=True): self.trjfile = ncfile def is_periodic(self, ts=None): - """Return ``True`` if :class:`Timestep` *ts* contains a valid - simulation box + """Test if `Timestep` contains a periodic trajectory. + + Parameters + ---------- + ts : :class:`Timestep` + :class:`Timestep` instance containing coordinates to + be written to trajectory file; default is the current + timestep + + Returns + ------- + bool + Return ``True`` if `ts` contains a valid simulation box """ ts = ts if ts is not None else self.ts return np.all(ts.dimensions > 0) def write_next_timestep(self, ts=None): - '''write a new timestep to the trj file - - *ts* is a :class:`Timestep` instance containing coordinates to - be written to trajectory file - ''' + """write a new timestep to the trj file + + Parameters + ---------- + ts : :class:`Timestep` + :class:`Timestep` instance containing coordinates to + be written to trajectory file; default is the current + timestep + """ if ts is None: ts = self.ts if ts is None: diff --git a/package/MDAnalysis/coordinates/TRR.py b/package/MDAnalysis/coordinates/TRR.py index 606a286d7c7..edeffd2991d 100644 --- a/package/MDAnalysis/coordinates/TRR.py +++ b/package/MDAnalysis/coordinates/TRR.py @@ -38,14 +38,17 @@ class TRRWriter(XDRBaseWriter): - """The Gromacs TRR trajectory format is a lossless format. The TRR format can + """Writer for the Gromacs TRR format. + + The Gromacs TRR trajectory format is a lossless format. The TRR format can store *velocoties* and *forces* in addition to the coordinates. It is also used by other Gromacs tools to store and process other data such as modes from a principal component analysis. - If the data dictionary of a TimeStep contains the key 'lambda' the - corresponding value will be used as the lambda value for written TRR file. - If None is found the lambda is set to 0. + If the data dictionary of a :class:`Timestep` contains the key + 'lambda' the corresponding value will be used as the lambda value + for written TRR file. If ``None`` is found the lambda is set to 0. + """ format = 'TRR' @@ -59,7 +62,7 @@ def write_next_timestep(self, ts): Parameters ---------- - ts : TimeStep + ts : :class:`~base.Timestep` See Also -------- @@ -101,12 +104,15 @@ def write_next_timestep(self, ts): class TRRReader(XDRBaseReader): - """The Gromacs TRR trajectory format is a lossless format. The TRR format can + """Reader for the Gromacs TRR format. + + The Gromacs TRR trajectory format is a lossless format. The TRR format can store *velocoties* and *forces* in addition to the coordinates. It is also used by other Gromacs tools to store and process other data such as modes from a principal component analysis. - The lambda value is written in the data dictionary of the returned TimeStep + The lambda value is written in the data dictionary of the returned + :class:`Timestep` Notes ----- diff --git a/package/MDAnalysis/coordinates/TRZ.py b/package/MDAnalysis/coordinates/TRZ.py index 371bfe7c82c..0788f79600d 100644 --- a/package/MDAnalysis/coordinates/TRZ.py +++ b/package/MDAnalysis/coordinates/TRZ.py @@ -32,6 +32,9 @@ .. _IBIsCO: http://www.theo.chemie.tu-darmstadt.de/ibisco/IBISCO.html .. _YASP: http://www.theo.chemie.tu-darmstadt.de/group/services/yaspdoc/yaspdoc.html +Classes +------- + .. autoclass:: MDAnalysis.coordinates.TRZ.Timestep :members: @@ -151,12 +154,13 @@ class TRZReader(base.ReaderBase): def __init__(self, trzfilename, n_atoms=None, **kwargs): """Creates a TRZ Reader - :Arguments: - *trzfilename* + Parameters + ---------- + trzfilename : str name of input file - *n_atoms* - number of atoms in trajectory, must taken from topology file! - *convert_units* + n_atoms : int + number of atoms in trajectory, must be taken from topology file! + convert_units : bool (optional) converts units to MDAnalysis defaults """ super(TRZReader, self).__init__(trzfilename, **kwargs) @@ -442,20 +446,19 @@ class TRZWriter(base.WriterBase): def __init__(self, filename, n_atoms, title='TRZ', convert_units=None): """Create a TRZWriter - :Arguments: - *filename* - name of output file - *n_atoms* - number of atoms in trajectory - - :Keywords: - *title* - title of the trajectory; the title must be 80 characters or shorter, - a longer title raises a ValueError exception. - *convert_units* - units are converted to the MDAnalysis base format; ``None`` selects - the value of :data:`MDAnalysis.core.flags` ['convert_lengths']. - (see :ref:`flags-label`) + Parameters + ---------- + filename : str + name of output file + n_atoms : int + number of atoms in trajectory + title : str (optional) + title of the trajectory; the title must be 80 characters or + shorter, a longer title raises a ValueError exception. + convert_units : bool (optional) + units are converted to the MDAnalysis base format; ``None`` selects + the value of :data:`MDAnalysis.core.flags` ['convert_lengths']. + (see :ref:`flags-label`) """ self.filename = filename if n_atoms is None: diff --git a/package/MDAnalysis/coordinates/XDR.py b/package/MDAnalysis/coordinates/XDR.py index 2a10db5ba4a..0104c67bc79 100644 --- a/package/MDAnalysis/coordinates/XDR.py +++ b/package/MDAnalysis/coordinates/XDR.py @@ -112,7 +112,8 @@ class XDRBaseReader(base.ReaderBase): """ def __init__(self, filename, convert_units=True, sub=None, refresh_offsets=False, **kwargs): - """Parameters + """ + Parameters ---------- filename : str trajectory filename diff --git a/package/MDAnalysis/coordinates/XTC.py b/package/MDAnalysis/coordinates/XTC.py index 27ff8eb8313..5788cb70d2e 100644 --- a/package/MDAnalysis/coordinates/XTC.py +++ b/package/MDAnalysis/coordinates/XTC.py @@ -38,7 +38,9 @@ class XTCWriter(XDRBaseWriter): - """XTC is a compressed trajectory format from Gromacs. The trajectory is saved + """Writer for the Gromacs XTC trajectory format. + + XTC is a compressed trajectory format from Gromacs. The trajectory is saved with reduced precision (3 decimal places by default) compared to other lossless formarts like TRR and DCD. The main advantage of XTC files is that they require significantly less disk space and the loss of precision is @@ -51,7 +53,8 @@ class XTCWriter(XDRBaseWriter): def __init__(self, filename, n_atoms, convert_units=True, precision=3, **kwargs): - """Parameters + """ + Parameters ---------- filename : str filename of the trajectory @@ -71,7 +74,7 @@ def write_next_timestep(self, ts): Parameters ---------- - ts: TimeStep + ts : :class:`~base.Timestep` See Also -------- @@ -96,7 +99,9 @@ def write_next_timestep(self, ts): class XTCReader(XDRBaseReader): - """XTC is a compressed trajectory format from Gromacs. The trajectory is saved + """Reader for the Gromacs XTC trajectory format. + + XTC is a compressed trajectory format from Gromacs. The trajectory is saved with reduced precision (3 decimal places) compared to other lossless formarts like TRR and DCD. The main advantage of XTC files is that they require significantly less disk space and the loss of precision is usually diff --git a/package/MDAnalysis/coordinates/XYZ.py b/package/MDAnalysis/coordinates/XYZ.py index 02e08348f4f..a92acd89924 100644 --- a/package/MDAnalysis/coordinates/XYZ.py +++ b/package/MDAnalysis/coordinates/XYZ.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -64,16 +64,21 @@ ... atomN x y z [ ... ] line N+2 -.. Note:: - * comment lines not implemented (do not include them) - * molecule name: the line is required but the content is ignored - at the moment - * optional data (after the coordinates) are presently ignored + +Note +---- +* comment lines not implemented (do not include them) +* molecule name: the line is required but the content is ignored + at the moment +* optional data (after the coordinates) are presently ignored .. Links .. _`VMD xyzplugin`: http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/xyzplugin.html +Classes +------- + """ from __future__ import division, absolute_import import six @@ -176,19 +181,17 @@ def close(self): self._xyz = None def write(self, obj): - """Write object *obj* at current trajectory frame to file. - - *obj* can be a :class:`~MDAnalysis.core.groups.AtomGroup`) - or a whole :class:`~MDAnalysis.core.universe.Universe`. + """Write object `obj` at current trajectory frame to file. - Atom names in the output are taken from the *obj* or default - to the value of the *atoms* keyword supplied to the + Atom names in the output are taken from the `obj` or default + to the value of the `atoms` keyword supplied to the :class:`XYZWriter` constructor. - :Arguments: - *obj* - :class:`~MDAnalysis.core.groups.AtomGroup` or - :class:`~MDAnalysis.core.universe.Universe` + Parameters + ---------- + obj : Universe or AtomGroup + The :class:`~MDAnalysis.core.groups.AtomGroup` or + :class:`~MDAnalysis.core.universe.Universe` to write. """ # prepare the Timestep and extract atom names if possible # (The way it is written it should be possible to write diff --git a/package/MDAnalysis/coordinates/base.py b/package/MDAnalysis/coordinates/base.py index 3da3437cdef..f882eefe15c 100644 --- a/package/MDAnalysis/coordinates/base.py +++ b/package/MDAnalysis/coordinates/base.py @@ -29,6 +29,13 @@ this module. The derived classes must follow the :ref:`Trajectory API` in :mod:`MDAnalysis.coordinates.__init__`. +Timestep +-------- + +A :class:`Timestep` holds information for the current time frame in +the trajectory. It is one of the central data structures in +MDAnalysis. + .. class:: Timestep .. automethod:: __init__ @@ -107,20 +114,63 @@ .. automethod:: copy .. automethod:: copy_slice -.. autoclass:: IOBase - :members: -.. autoclass:: ProtoReader - :members: +Readers +------- + +Readers know how to take trajectory data in a given format and present it in a +common API to the user in MDAnalysis. There are two types of readers: + +1. Readers for *multi frame trajectories*, i.e., file formats that typically + contain many frames. These readers are typically derived from + :class:`ReaderBase`. + +2. Readers for *single frame formats*: These file formats only contain a single + coordinate set. These readers are derived from + :class`:SingleFrameReaderBase`. + +The underlying low-level readers handle closing of files in different +ways. Typically, the MDAnalysis readers try to ensure that files are always +closed when a reader instance is garbage collected, which relies on +implementing a :meth:`~ReaderBase.__del__` method. However, in some cases, this +is not necessary (for instance, for the single frame formats) and then such a +method can lead to undesirable side effects (such as memory leaks). In this +case, :class:`ProtoReader` should be used. + .. autoclass:: ReaderBase :members: :inherited-members: +.. autoclass:: SingleFrameReaderBase + :members: + :inherited-members: + +.. autoclass:: ProtoReader + :members: + + + +Writers +------- + +Writers know how to write information in a :class:`Timestep` to a trajectory +file. + .. autoclass:: WriterBase :members: :inherited-members: + +Helper classes +-------------- + +The following classes contain basic functionality that all readers and +writers share. + +.. autoclass:: IOBase + :members: + """ from __future__ import absolute_import import six @@ -158,10 +208,10 @@ class Timestep(object): .. versionchanged:: 0.11.0 Added :meth:`from_timestep` and :meth:`from_coordinates` constructor methods. - :class:`Timestep` init now only accepts integer creation - :attr:`n_atoms` now a read only property - :attr:`frame` now 0-based instead of 1-based - Attributes status and step removed + :class:`Timestep` init now only accepts integer creation. + :attr:`n_atoms` now a read only property. + :attr:`frame` now 0-based instead of 1-based. + Attributes `status` and `step` removed. """ order = 'F' @@ -174,23 +224,24 @@ def __init__(self, n_atoms, **kwargs): The total number of atoms this Timestep describes positions : bool, optional Whether this Timestep has position information [``True``] - velocities : bool, optional + velocities : bool (optional) Whether this Timestep has velocity information [``False``] - forces : bool, optional + forces : bool (optional) Whether this Timestep has force information [``False``] - reader : Reader, optional + reader : Reader (optional) A weak reference to the owning Reader. Used for when attributes require trajectory manipulation (e.g. dt) - dt : float, optional + dt : float (optional) The time difference between frames (ps). If :attr:`time` is set, then `dt` will be ignored. - time_offset : float, optional - The starting time from which to calculate time (ps) + time_offset : float (optional) + The starting time from which to calculate time (in ps) + - .. versionchanged:: 0.11.0 - Added keywords for `positions`, `velocities` and `forces`. - Can add and remove position/velocity/force information by using - the ``has_*`` attribute. + .. versionchanged:: 0.11.0 + Added keywords for `positions`, `velocities` and `forces`. + Can add and remove position/velocity/force information by using + the ``has_*`` attribute. """ # readers call Reader._read_next_timestep() on init, incrementing # self.frame to 0 @@ -363,7 +414,7 @@ def __getitem__(self, atoms): correspond to atom indices, :attr:`MDAnalysis.core.groups.Atom.index` (0-based) """ - if isinstance(atoms, int): + if isinstance(atoms, numbers.Integral): return self._pos[atoms] elif isinstance(atoms, (slice, np.ndarray)): return self._pos[atoms] @@ -399,25 +450,41 @@ def __deepcopy__(self): return self.from_timestep(self) def copy_slice(self, sel): - """Make a new Timestep containing a subset of the original Timestep. + """Make a new `Timestep` containing a subset of the original `Timestep`. - ``ts.copy_slice(slice(start, stop, skip))`` - ``ts.copy_slice([list of indices])`` + Parameters + ---------- + sel : array_like or slice + The underlying position, velocity, and force arrays are sliced + using a :class:`list`, :class:`slice`, or any array-like. Returns ------- - A Timestep object of the same type containing all header - information and all atom information relevant to the selection. + :class:`Timestep` + A `Timestep` object of the same type containing all header + information and all atom information relevant to the selection. Note ---- - The selection must be a 0 based slice or array of the atom indices - in this Timestep + The selection must be a 0 based :class:`slice` or array of the atom indices + in this :class:`Timestep` + + Example + ------- + Using a Python :class:`slice` object:: + + new_ts = ts.copy_slice(slice(start, stop, step)) + + Using a list of indices:: + + new_ts = ts.copy_slice([0, 2, 10, 20, 23]) + .. versionadded:: 0.8 .. versionchanged:: 0.11.0 Reworked to follow new Timestep API. Now will strictly only copy official attributes of the Timestep. + """ # Detect the size of the Timestep by doing a dummy slice try: @@ -511,16 +578,17 @@ def positions(self): Returns ------- - A numpy.ndarray of shape (n_atoms, 3) of position data for each - atom + positions : numpy.ndarray with dtype numpy.float32 + position data of shape ``(n_atoms, 3)`` for all atoms Raises ------ - :class:`MDAnalysis.exceptions.NoDataError` - If the Timestep has no position data + :exc:`MDAnalysis.exceptions.NoDataError` + if the Timestep has no position data + .. versionchanged:: 0.11.0 - Now can raise NoDataError when no position data present + Now can raise :exc`NoDataError` when no position data present """ if self.has_positions: return self._pos @@ -588,13 +656,14 @@ def velocities(self): Returns ------- - A numpy.ndarray of shape (n_atoms, 3) of velocity data for each - atom + velocities : numpy.ndarray with dtype numpy.float32 + velocity data of shape ``(n_atoms, 3)`` for all atoms Raises ------ - :class:`MDAnalysis.exceptions.NoDataError` - When the Timestep does not contain velocity information + :exc:`MDAnalysis.exceptions.NoDataError` + if the Timestep has no velocity data + .. versionadded:: 0.11.0 """ @@ -637,13 +706,14 @@ def forces(self): Returns ------- - A numpy.ndarray of shape (n_atoms, 3) of force data for each - atom + forces : numpy.ndarray with dtype numpy.float32 + force data of shape ``(n_atoms, 3)`` for all atoms Raises ------ - :class:`MDAnalysis.NoDataError` - When the Timestep does not contain force information + :exc:`MDAnalysis.exceptions.NoDataError` + if the Timestep has no force data + .. versionadded:: 0.11.0 """ @@ -688,7 +758,8 @@ def triclinic_dimensions(self): Returns ------- - A (3, 3) numpy.ndarray of unit cell vectors + numpy.ndarray + A (3, 3) numpy.ndarray of unit cell vectors Examples -------- @@ -735,6 +806,7 @@ def dt(self): ---- This defaults to 1.0 ps in the absence of time data + .. versionadded:: 0.11.0 """ try: @@ -804,17 +876,20 @@ def convert_pos_from_native(self, x, inplace=True): ---------- x : array_like Positions to transform - inplace : bool, optional + inplace : bool (optional) Whether to modify the array inplace, overwriting previous data Note ---- - By default, the input *x* is modified in place and also returned. + By default, the input `x` is modified in place and also returned. + In-place operations improve performance because allocating new arrays + is avoided. + .. versionchanged:: 0.7.5 - Keyword *inplace* can be set to ``False`` so that a + Keyword `inplace` can be set to ``False`` so that a modified copy is returned *unless* no conversion takes - place, in which case the reference to the unmodified *x* is + place, in which case the reference to the unmodified `x` is returned. """ @@ -834,12 +909,15 @@ def convert_velocities_from_native(self, v, inplace=True): ---------- v : array_like Velocities to transform - inplace : bool, optional + inplace : bool (optional) Whether to modify the array inplace, overwriting previous data Note ---- By default, the input *v* is modified in place and also returned. + In-place operations improve performance because allocating new arrays + is avoided. + .. versionadded:: 0.7.5 """ @@ -859,12 +937,14 @@ def convert_forces_from_native(self, force, inplace=True): ---------- force : array_like Forces to transform - inplace : bool, optional + inplace : bool (optional) Whether to modify the array inplace, overwriting previous data Note ---- By default, the input *force* is modified in place and also returned. + In-place operations improve performance because allocating new arrays + is avoided. .. versionadded:: 0.7.7 """ @@ -884,20 +964,22 @@ def convert_time_from_native(self, t, inplace=True): ---------- t : array_like Time values to transform - inplace : bool, optional + inplace : bool (optional) Whether to modify the array inplace, overwriting previous data Note ---- - By default, the input *t* is modified in place and also - returned (although note that scalar values *t* are passed by - value in Python and hence an in-place modification has no - effect on the caller.) + By default, the input `t` is modified in place and also returned + (although note that scalar values `t` are passed by value in Python and + hence an in-place modification has no effect on the caller.) In-place + operations improve performance because allocating new arrays is + avoided. + .. versionchanged:: 0.7.5 - Keyword *inplace* can be set to ``False`` so that a + Keyword `inplace` can be set to ``False`` so that a modified copy is returned *unless* no conversion takes - place, in which case the reference to the unmodified *x* is + place, in which case the reference to the unmodified `x` is returned. """ @@ -911,23 +993,26 @@ def convert_time_from_native(self, t, inplace=True): return t def convert_pos_to_native(self, x, inplace=True): - """Conversion of coordinate array x from base units to native units. + """Conversion of coordinate array `x` from base units to native units. Parameters ---------- x : array_like Positions to transform - inplace : bool, optional + inplace : bool (optional) Whether to modify the array inplace, overwriting previous data Note ---- - By default, the input *x* is modified in place and also returned. + By default, the input `x` is modified in place and also returned. + In-place operations improve performance because allocating new arrays + is avoided. + .. versionchanged:: 0.7.5 - Keyword *inplace* can be set to ``False`` so that a + Keyword `inplace` can be set to ``False`` so that a modified copy is returned *unless* no conversion takes - place, in which case the reference to the unmodified *x* is + place, in which case the reference to the unmodified `x` is returned. """ @@ -941,18 +1026,21 @@ def convert_pos_to_native(self, x, inplace=True): return x def convert_velocities_to_native(self, v, inplace=True): - """Conversion of coordinate array *v* from base to native units + """Conversion of coordinate array `v` from base to native units Parameters ---------- v : array_like Velocities to transform - inplace : bool, optional + inplace : bool (optional) Whether to modify the array inplace, overwriting previous data Note ---- - By default, the input *v* is modified in place and also returned. + By default, the input `v` is modified in place and also returned. + In-place operations improve performance because allocating new arrays + is avoided. + .. versionadded:: 0.7.5 """ @@ -972,12 +1060,15 @@ def convert_forces_to_native(self, force, inplace=True): ---------- force : array_like Forces to transform - inplace : bool, optional + inplace : bool (optional) Whether to modify the array inplace, overwriting previous data Note ---- - By default, the input *force* is modified in place and also returned. + By default, the input `force` is modified in place and also returned. + In-place operations improve performance because allocating new arrays + is avoided. + .. versionadded:: 0.7.7 """ @@ -1066,6 +1157,7 @@ class ProtoReader(six.with_metaclass(_Readermeta, IOBase)): -------- :class:`ReaderBase` + .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based """ @@ -1150,9 +1242,11 @@ def OtherWriter(self, filename, **kwargs): Sets the default keywords *start*, *step* and *dt* (if available). *n_atoms* is always set from :attr:`Reader.n_atoms`. + See Also -------- :meth:`Reader.Writer` and :func:`MDAnalysis.Writer` + """ kwargs['n_atoms'] = self.n_atoms # essential kwargs.setdefault('start', self.frame) @@ -1186,7 +1280,7 @@ def _reopen(self): def __getitem__(self, frame): """Return the Timestep corresponding to *frame*. - If *frame* is a integer then the corresponding frame is + If `frame` is a integer then the corresponding frame is returned. Negative numbers are counted from the end. If frame is a :class:`slice` then an iterator is returned that @@ -1205,7 +1299,7 @@ def apply_limits(frame): "".format(frame, len(self))) return frame - if isinstance(frame, int): + if isinstance(frame, numbers.Integral): frame = apply_limits(frame) return self._read_frame_with_aux(frame) elif isinstance(frame, (list, np.ndarray)): @@ -1217,7 +1311,7 @@ def apply_limits(frame): def listiter(frames): for f in frames: - if not isinstance(f, (int, np.integer)): + if not isinstance(f, numbers.Integral): raise TypeError("Frames indices must be integers") yield self._read_frame_with_aux(apply_limits(f)) @@ -1271,33 +1365,51 @@ def _sliced_iter(self, start, stop, step): "".format(self.__class__.__name__)) def check_slice_indices(self, start, stop, step): - """Check frame indices are valid and clip to fit trajectory + """Check frame indices are valid and clip to fit trajectory. + + The usage follows standard Python conventions for :func:`range` but see + the warning below. Parameters ---------- - start, stop, step : int or None - Values representing the slice indices. - Can use `None` to use defaults of (0, n_frames, and 1) - respectively. + start : int or None + Starting frame index (inclusive). ``None`` corresponds to the default + of 0, i.e., the initial frame. + stop : int or None + Last frame index (exclusive). ``None`` corresponds to the default + of n_frames, i.e., it includes the last frame of the trajectory. + step : int or None + step size of the slice, ``None`` corresponds to the default of 1, i.e, + include every frame in the range `start`, `stop`. Returns ------- - start, stop, step : int + start, stop, step : tuple (int, int, int) Integers representing the slice Warning ------- - The returned values start, stop and step give the expected result when passed - in range() but gives unexpected behaviour when passed in a slice when stop=None - and step=-1 + The returned values `start`, `stop` and `step` give the expected result + when passed in :func:`range` but gives unexpected behavior when passed + in a :class:`slice` when ``stop=None`` and ``step=-1`` - This is because when we slice the trajectory (u.trajectory[::-1]), the values - returned by check_slice_indices are passed to range. Instead, in AnalysisBase - the values returned by check_slice_indices are used to splice the trajectory. - This creates a discrepancy because these two lines are not equivalent: + This can be a problem for downstream processing of the output from this + method. For example, slicing of trajectories is implemented by passing + the values returned by :meth:`check_slice_indices` to :func:`range` :: - range(10, -1, -1) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - range(10)[10:-1:-1] # [] + range(start, stop, step) + + and using them as the indices to randomly seek to. On the other hand, + in :class:`MDAnalysis.analysis.base.AnalysisBase` the values returned + by :meth:`check_slice_indices` are used to splice the trajectory by + creating a :class:`slice` instance :: + + slice(start, stop, step) + + This creates a discrepancy because these two lines are not equivalent:: + + range(10, -1, -1) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] + range(10)[slice(10, -1, -1)] # [] """ @@ -1357,7 +1469,7 @@ def add_auxiliary(self, auxname, auxdata, format=None, **kwargs): :class:`~MDAnalysis.auxiliary.base.AuxReader` instance, or the data itself as e.g. a filename; in the latter case an appropriate :class:`~MDAnalysis.auxiliary.base.AuxReader` is guessed from the - data/file format. An appropriate *format* may also be directly provided + data/file format. An appropriate `format` may also be directly provided as a key word argument. On adding, the AuxReader is initially matched to the current timestep @@ -1628,6 +1740,7 @@ class ReaderBase(ProtoReader): -------- :class:`ProtoReader` + .. versionchanged:: 0.11.0 Most of the base Reader class definitions were offloaded to :class:`ProtoReader` so as to allow the subclassing of ReaderBases without a @@ -1712,15 +1825,17 @@ def convert_dimensions_to_unitcell(self, ts, inplace=True): return np.concatenate([lengths, angles]) def write(self, obj): - """Write current timestep, using the supplied *obj*. + """Write current timestep, using the supplied `obj`. - The argument should be a :class:`~MDAnalysis.core.groups.AtomGroup` or - a :class:`~MDAnalysis.core.universe.Universe` or a :class:`Timestep` instance. - - .. Note:: + Parameters + ---------- + obj : :class:`~MDAnalysis.core.groups.AtomGroup` or :class:`~MDAnalysis.core.universe.Universe` or a :class:`Timestep` + write coordinate information associate with `obj` - The size of the *obj* must be the same as the number of atom - provided when setting up the trajectory. + Note + ---- + The size of the `obj` must be the same as the number of atoms provided + when setting up the trajectory. """ if isinstance(obj, Timestep): ts = obj @@ -1753,12 +1868,16 @@ def has_valid_coordinates(self, criteria, x): min < x <= max - :Arguments: - *criteria* - dictionary containing the *max* and *min* values in native units - *x* - :class:`np.ndarray` of ``(x, y, z)`` coordinates of atoms selected to be written out. - :Returns: boolean + Parameters + ---------- + criteria : dict + dictionary containing the *max* and *min* values in native units + x : numpy.ndarray + ``(x, y, z)`` coordinates of atoms selected to be written out + + Returns + ------- + bool """ x = np.ravel(x) return np.all(criteria["min"] < x) and np.all(x <= criteria["max"]) diff --git a/package/MDAnalysis/coordinates/chain.py b/package/MDAnalysis/coordinates/chain.py index 0497f333ba6..c706383f9f9 100644 --- a/package/MDAnalysis/coordinates/chain.py +++ b/package/MDAnalysis/coordinates/chain.py @@ -69,6 +69,7 @@ class ChainReader(base.ProtoReader): :attr:`ChainReader.n_atoms`, and :attr:`ChainReader.fixed` are properly set, though + .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based .. versionchanged:: 0.13.0 @@ -94,17 +95,17 @@ def __init__(self, filenames, **kwargs): names in either plain file names format or ``(filename, format)`` tuple combination. This allows explicit setting of the format for each individual trajectory file. - skip : int, optional + skip : int (optional) skip step (also passed on to the individual trajectory readers); must be same for all trajectories - dt : float, optional + dt : float (optional) Passed to individual trajectory readers to enforce a common time difference between frames, in MDAnalysis time units. If not set, each reader's `dt` will be used (either inferred from the trajectory files, or set to the reader's default) when reporting frame times; note that this might lead an inconsistent time difference between frames. - **kwargs : dict, optional + **kwargs : dict (optional) all other keyword arguments are passed on to each trajectory reader unchanged @@ -173,7 +174,7 @@ def _get_local_frame(self, k): Returns ------- (i, f) : tuple - **local frame** tuple ` + **local frame** tuple Raises ------ diff --git a/package/MDAnalysis/coordinates/core.py b/package/MDAnalysis/coordinates/core.py index 91ded0e5b0d..7338b2ad7fa 100644 --- a/package/MDAnalysis/coordinates/core.py +++ b/package/MDAnalysis/coordinates/core.py @@ -65,17 +65,14 @@ def reader(filename, **kwargs): Returns ------- - A Reader object + :class:`~base.Reader` + A trajectory Reader instance See Also -------- :ref:`Supported coordinate formats` - .. deprecated:: 0.15.0 - The "permissive" flag is not used anymore (and effectively - defaults to True); it will be completely removed in 0.16.0. - """ if isinstance(filename, tuple): Reader = get_reader_for(filename[0], @@ -94,10 +91,10 @@ def writer(filename, n_atoms=None, **kwargs): filename : str Output filename of the trajectory; the extension determines the format. - n_atoms : int, optional + n_atoms : int (optional) The number of atoms in the output trajectory; can be ommitted for single-frame writers. - multiframe : bool, optional + multiframe : bool (optional) ``True``: write a trajectory with multiple frames; ``False`` only write a single frame snapshot; ``None`` first try to get a multiframe writer and then fall back to single frame [``None``] @@ -110,7 +107,8 @@ def writer(filename, n_atoms=None, **kwargs): Returns ------- - A Writer object + :class:`~base.Writer` + A trajectory Writer instance See Also -------- @@ -118,7 +116,7 @@ def writer(filename, n_atoms=None, **kwargs): .. versionchanged:: 0.7.6 - Added *multiframe* keyword. See also :func:`get_writer_for`. + Added `multiframe` keyword. See also :func:`get_writer_for`. """ Writer = get_writer_for(filename, format=kwargs.pop('format', None), diff --git a/package/MDAnalysis/coordinates/memory.py b/package/MDAnalysis/coordinates/memory.py index 418ef6801b0..279009fbfd3 100644 --- a/package/MDAnalysis/coordinates/memory.py +++ b/package/MDAnalysis/coordinates/memory.py @@ -217,6 +217,9 @@ class MemoryReader(base.ProtoReader): A trajectory reader interface to a numpy array of the coordinates. For compatibility with the timeseries interface, support is provided for specifying the order of columns through the format option. + + .. versionadded:: 0.16.0 + """ format = 'MEMORY' @@ -225,27 +228,34 @@ class MemoryReader(base.ProtoReader): def __init__(self, coordinate_array, order='fac', dimensions=None, dt=1, filename=None, **kwargs): """ - Parameters ---------- - coordinate_array : :class:`~numpy.ndarray` object + coordinate_array : numpy.ndarray The underlying array of coordinates - order : str, optional + order : {"afc", "acf", "caf", "fac", "fca", "cfa"} (optional) the order/shape of the return data array, corresponding to (a)tom, (f)rame, (c)oordinates all six combinations of 'a', 'f', 'c' are allowed ie "fac" - return array where the shape is (frame, number of atoms, - coordinates) - dimensions: (*A*, *B*, *C*, *alpha*, *beta*, *gamma*), optional + coordinates). + dimensions: [A, B, C, alpha, beta, gamma] (optional) unitcell dimensions (*A*, *B*, *C*, *alpha*, *beta*, *gamma*) lengths *A*, *B*, *C* are in the MDAnalysis length unit (Å), and angles are in degrees. - dt: float, optional + dt: float (optional) The time difference between frames (ps). If :attr:`time` is set, then `dt` will be ignored. - filename: string, optional - The name of the file from which this instance is created. Set to None + filename: string (optional) + The name of the file from which this instance is created. Set to ``None`` when created from an array + + Note + ---- + At the moment, only a fixed `dimension` is supported, i.e., the same + unit cell for all frames in `coordinate_array`. See issue `#1041`_. + + .. _`#1041`: https://github.com/MDAnalysis/mdanalysis/issues/1041 + """ super(MemoryReader, self).__init__() @@ -282,12 +292,12 @@ def set_array(self, coordinate_array, order='fac'): ---------- coordinate_array : :class:`~numpy.ndarray` object The underlying array of coordinates - order - The order/shape of the return data array, corresponding + order : {"afc", "acf", "caf", "fac", "fca", "cfa"} (optional) + the order/shape of the return data array, corresponding to (a)tom, (f)rame, (c)oordinates all six combinations of 'a', 'f', 'c' are allowed ie "fac" - return array where the shape is (frame, number of atoms, - coordinates) + coordinates). """ # Only make copy if not already in float32 format self.coordinate_array = coordinate_array.astype('float32', copy=False) @@ -307,29 +317,36 @@ def _reopen(self): def timeseries(self, asel=None, start=0, stop=-1, step=1, format='afc'): """Return a subset of coordinate data for an AtomGroup in desired column order/format. If no selection is given, it will return a view of - the underlying array, while a copy is returned otherwise. + the underlying array, while a copy is returned otherwise. Parameters --------- - asel : :class:`~MDAnalysis.core.groups.AtomGroup` object - Atom selection. Defaults to None, in which case the full set of + asel : AtomGroup (optional) + Atom selection. Defaults to ``None``, in which case the full set of coordinate data is returned. Note that in this case, a view of the underlying numpy array is returned, while a copy of the - data is returned whenever asel is different from None. - start, stop, skip : int - range of trajectory to access, start and stop are inclusive - format : str + data is returned whenever `asel` is different from ``None``. + start : int (optional) + stop : int (optional) + step : int (optional) + range of trajectory to access, `start` and `stop` are *inclusive* + format : {"afc", "acf", "caf", "fac", "fca", "cfa"} (optional) the order/shape of the return data array, corresponding to (a)tom, (f)rame, (c)oordinates all six combinations of 'a', 'f', 'c' are allowed ie "fac" - return array where the shape is (frame, number of atoms, - coordinates). + coordinates). + + Note + ---- + The `format` parameter name is used to mimic the + :class:`MDAnalysis.coordinates.DCD.timeseries` interface. It is + identical to the `order` parameter for :class:`MemoryReader`. In a + future version, `format` will be renamed to `order`. """ - - # The "format" name is used for compliance with DCD.timeseries - # Renaming it to order here for internal consistency in this class + # Renaming 'format' to 'order' here for internal consistency in this class order = format - + array = self.get_array() if order == self.stored_order: pass diff --git a/package/MDAnalysis/coordinates/null.py b/package/MDAnalysis/coordinates/null.py index a5947c59bfb..30daa411d8b 100644 --- a/package/MDAnalysis/coordinates/null.py +++ b/package/MDAnalysis/coordinates/null.py @@ -29,6 +29,12 @@ This class exists to allow developers writing generic code and tests. +Classes +------- + +.. autoclass:: NullWriter + :members: + """ from __future__ import absolute_import @@ -41,7 +47,6 @@ class NullWriter(base.WriterBase): The NullWriter is the equivalent to ``/dev/null``: it behaves like a Writer but ignores all input. It can be used in order to suppress output. - """ format = 'NULL' multiframe = True diff --git a/package/MDAnalysis/core/__init__.py b/package/MDAnalysis/core/__init__.py index d70225677be..2101c1d878e 100644 --- a/package/MDAnalysis/core/__init__.py +++ b/package/MDAnalysis/core/__init__.py @@ -21,21 +21,20 @@ # -""" -Core functions of MDAnalysis +"""Core functions of MDAnalysis ============================ -The basic class is an :class:`~MDAnalysis.core.groups.AtomGroup`; -the whole simulation is called the -:class:`~MDAnalysis.core.universe.Universe`. Selections are computed -on an :class:`~MDAnalysis.core.groups.AtomGroup` and return another +The basic class is an :class:`~MDAnalysis.core.groups.AtomGroup`; the whole +simulation is called the +:class:`~MDAnalysis.core.universe.Universe`. Selections are computed on an +:class:`~MDAnalysis.core.groups.AtomGroup` and return another :class:`~MDAnalysis.core.groups.AtomGroup`. :mod:`~MDAnalysis.Timeseries` are a convenient way to analyse trajectories. To get started, load the Universe:: - u = Universe(psffilename,dcdfilename) + u = Universe(topology_file, trajectory_file) A simple selection of all water oxygens within 4 A of the protein:: @@ -43,9 +42,9 @@ water_shell.n_atoms # how many waters were selected water_shell.total_mass() # their total mass -:class:`AtomGroup` instances have various methods that allow -calculation of simple properties. For more complicated analysis, -obtain the coordinates as a numpy array :: +:class:`~MDAnalysis.core.groups.AtomGroup` instances have various methods that +allow calculation of simple properties. For more complicated analysis, obtain +the coordinates as a numpy array :: coords = water_shell.positions @@ -85,7 +84,6 @@ .. autoclass:: Flag :members: - """ from __future__ import absolute_import @@ -185,20 +183,19 @@ class Flag(object): """A Flag, essentially a variable that knows its default and legal values.""" def __init__(self, name, default, mapping=None, doc=None): - """Create a new flag which will be registered with FLags. + """Create a new flag which will be registered with Flags. - newflag = Flag(name,default,mapping,doc) - - :Arguments: - *name* + Parameters + ---------- + name : str name of the flag, must be a legal python name - *default* + default default value - *mapping* + mapping : dict dict that maps allowed input values to canonical values; if ``None`` then no argument checking will be performed and all values are directly set. - *doc* + doc : str doc string; may contain string interpolation mappings for:: %%(name)s name of the flag @@ -207,6 +204,14 @@ def __init__(self, name, default, mapping=None, doc=None): %%(mapping)r mapping Doc strings are generated dynamically and reflect the current state. + + + Example + ------- + Create a new flag:: + + newflag = Flag(name, default, mapping, doc) + """ self.name = name self.value = default @@ -265,8 +270,8 @@ def __doc__(self): 'use_KDTree_routines', 'fast', {True: 'fast', 'fast': 'fast', # only KDTree if advantageous - 'always': 'always', # always even if slower (for testing) - False: 'never', 'never': 'never'}, # never, only use (slower) alternatives + 'always': 'always', # always even if slower (for testing) + False: 'never', 'never': 'never'}, # never, only use (slower) alternatives """ Determines which KDTree routines are used for distance selections diff --git a/package/MDAnalysis/core/_get_readers.py b/package/MDAnalysis/core/_get_readers.py index 0fb91715a2b..325bfad5d0c 100644 --- a/package/MDAnalysis/core/_get_readers.py +++ b/package/MDAnalysis/core/_get_readers.py @@ -39,7 +39,7 @@ def get_reader_for(filename, format=None): filename filename of the input trajectory or coordinate file. Also can handle a few special cases, see notes below. - format + format : str or :class:`Reader` (optional) Define the desired format. Can be a string to request a given Reader. If a class is passed, it will be assumed that this is @@ -47,7 +47,8 @@ def get_reader_for(filename, format=None): Returns ------- - A Reader object + :class:`Reader` + A Reader object Raises @@ -59,13 +60,19 @@ def get_reader_for(filename, format=None): Notes ----- There are a number of special cases that can be handled: - If `filename` is a numpy array, MemoryReader is returned. - If `filename` is an MMTF object, MMTFReader is returned. - If `filename` is an iterable of filenames, ChainReader is returned. - Automatic detection is disabled when an explicit `format` is - provided, unless a list of filenames is given, in which case - ChainReader is returned and `format` passed to the ChainReader. + - If `filename` is a numpy array, + :class:`~MDAnalysis.coordinates.memory.MemoryReader` is returned. + - If `filename` is an MMTF object, + :class:`~MDAnalysis.coordinates.MMTF.MMTFReader` is returned. + - If `filename` is an iterable of filenames, + :class:`~MDAnalysis.coordinates.chain.ChainReader` is returned. + + Automatic detection is disabled when an explicit `format` is provided, + unless a list of filenames is given, in which case + :class:`~MDAnalysis.coordinates.chain.ChainReader` is returned and `format` + passed to the :class:`~MDAnalysis.coordinates.chain.ChainReader`. + """ # check if format is actually a Reader if inspect.isclass(format): @@ -105,7 +112,7 @@ def get_writer_for(filename, format=None, multiframe=None): """Return an appropriate trajectory or frame writer class for `filename`. The format is determined by the `format` argument or the extension of - `filename`. If `format` is provided, it takes precedence over The + `filename`. If `format` is provided, it takes precedence over the extension of `filename`. Parameters @@ -113,18 +120,20 @@ def get_writer_for(filename, format=None, multiframe=None): filename : str or ``None`` If no *format* is supplied, then the filename for the trajectory is examined for its extension and the Writer is chosen accordingly. - If ``None`` is provided, the - :class:`~MDAnalysis.coordinates.null.NullWriter` is selected. - format : str, optional + If ``None`` is provided, then + :class:`~MDAnalysis.coordinates.null.NullWriter` is selected (and + all output is discarded silently). + format : str (optional) Explicitly set a format. - multiframe : bool, optional + multiframe : bool (optional) ``True``: write multiple frames to the trajectory; ``False``: only write a single coordinate frame; ``None``: first try trajectory (multi frame writers), then the single frame ones. Default is ``None``. Returns ------- - A Writer object + :class:`Writer` + A Writer object Raises ------ @@ -169,7 +178,7 @@ def get_writer_for(filename, format=None, multiframe=None): errmsg = "No trajectory or frame writer for format '{0}'" elif multiframe is True: options = _MULTIFRAME_WRITERS - errmsg = "No trajectory writer for format '{0}'" + errmsg = "No trajectory writer for format '{0}'" elif multiframe is False: options = _SINGLEFRAME_WRITERS errmsg = "No single frame writer for format '{0}'" @@ -190,10 +199,19 @@ def get_parser_for(filename, format=None): Automatic detection is disabled when an explicit `format` is provided. + Parameters + ---------- + filename : str or mmtf.MMTFDecoder + name of the topology file; if this is an instance of + :class:`mmtf.MMTFDecoder` then directly use the MMTF format. + format : str + description of the file format + Raises ------ ValueError If no appropriate parser could be found. + """ if inspect.isclass(format): return format diff --git a/package/MDAnalysis/core/groups.py b/package/MDAnalysis/core/groups.py index fab774af10f..c386e079ef0 100644 --- a/package/MDAnalysis/core/groups.py +++ b/package/MDAnalysis/core/groups.py @@ -97,6 +97,7 @@ import numpy as np import functools import itertools +import numbers import os import warnings @@ -433,7 +434,7 @@ def __getitem__(self, item): # because our _ix attribute is a numpy array # it can be sliced by all of these already, # so just return ourselves sliced by the item - if isinstance(item, (int, np.int_)): + if isinstance(item, numbers.Integral): return self.level.singular(self.ix[item], self.universe) else: if isinstance(item, list) and item: # check for empty list diff --git a/package/MDAnalysis/core/topologyattrs.py b/package/MDAnalysis/core/topologyattrs.py index 90535b582eb..9cdf56cfece 100644 --- a/package/MDAnalysis/core/topologyattrs.py +++ b/package/MDAnalysis/core/topologyattrs.py @@ -39,6 +39,7 @@ from collections import defaultdict import functools import itertools +import numbers import numpy as np from . import flags @@ -607,7 +608,7 @@ def __init__(self, values, guessed=False): def get_residues(self, rg): resatoms = self.top.tt.residues2atoms_2d(rg._ix) - if isinstance(rg._ix, int): + if isinstance(rg._ix, numbers.Integral): # for a single residue masses = self.values[resatoms].sum() else: @@ -621,7 +622,7 @@ def get_residues(self, rg): def get_segments(self, sg): segatoms = self.top.tt.segments2atoms_2d(sg._ix) - if isinstance(sg._ix, int): + if isinstance(sg._ix, numbers.Integral): # for a single segment masses = self.values[segatoms].sum() else: @@ -933,7 +934,7 @@ class Charges(AtomAttr): def get_residues(self, rg): resatoms = self.top.tt.residues2atoms_2d(rg._ix) - if isinstance(rg._ix, int): + if isinstance(rg._ix, numbers.Integral): charges = self.values[resatoms].sum() else: charges = np.empty(len(rg)) @@ -945,7 +946,7 @@ def get_residues(self, rg): def get_segments(self, sg): segatoms = self.top.tt.segments2atoms_2d(sg._ix) - if isinstance(sg._ix, int): + if isinstance(sg._ix, numbers.Integral): # for a single segment charges = self.values[segatoms].sum() else: diff --git a/package/MDAnalysis/core/topologyobjects.py b/package/MDAnalysis/core/topologyobjects.py index 5d8a794d472..384180ee683 100644 --- a/package/MDAnalysis/core/topologyobjects.py +++ b/package/MDAnalysis/core/topologyobjects.py @@ -30,6 +30,7 @@ from __future__ import print_function, absolute_import, division from six.moves import zip +import numbers import numpy as np import functools @@ -749,7 +750,7 @@ def __getitem__(self, item): Allows indexing via boolean numpy array """ # Grab a single Item, similar to Atom/AtomGroup relationship - if isinstance(item, int): + if isinstance(item, numbers.Integral): outclass = {'bond': Bond, 'angle': Angle, 'dihedral': Dihedral, diff --git a/package/MDAnalysis/core/universe.py b/package/MDAnalysis/core/universe.py index f19ed7cf9ec..3a6e3decacc 100644 --- a/package/MDAnalysis/core/universe.py +++ b/package/MDAnalysis/core/universe.py @@ -859,7 +859,9 @@ def as_Universe(*args, **kwargs): as_Universe(PSF, DCD, **kwargs) --> Universe(PSF, DCD, **kwargs) as_Universe(*args, **kwargs) --> Universe(*args, **kwargs) - :Returns: an instance of :class:`~MDAnalysis.core.groups.Universe` + Returns + ------- + :class:`~MDAnalysis.core.groups.Universe` """ if len(args) == 0: raise TypeError("as_Universe() takes at least one argument (%d given)" % len(args)) @@ -881,9 +883,12 @@ def Merge(*args): ------- universe : :class:`Universe` - :Raises: :exc:`ValueError` for too few arguments or if an AtomGroup is - empty and :exc:`TypeError` if arguments are not - :class:`AtomGroup` instances. + Raises + ------ + ValueError + Too few arguments or an AtomGroup is empty and + TypeError + Arguments are not :class:`AtomGroup` instances. Notes ----- diff --git a/package/MDAnalysis/lib/mdamath.py b/package/MDAnalysis/lib/mdamath.py index a20d3fb4e47..03183d2a608 100644 --- a/package/MDAnalysis/lib/mdamath.py +++ b/package/MDAnalysis/lib/mdamath.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors @@ -57,7 +57,7 @@ def norm(v): Parameters ---------- - v: array_like + v : array_like 1D array of shape (N) for a vector of length N Returns @@ -186,18 +186,23 @@ def triclinic_vectors(dimensions): .. _code by Tsjerk Wassenaar: http://www.mail-archive.com/gmx-users@gromacs.org/msg28032.html - :Arguments: - *dimensions* + Parameters + ---------- + dimensions : [A, B, C, alpha, beta, gamma] list of box lengths and angles (in degrees) such as - [A,B,C,alpha,beta,gamma] + ``[A,B,C,alpha,beta,gamma]`` - :Returns: numpy 3x3 array B, with B[0] = first box vector, - B[1] = second vector, B[2] third box vector. + Returns + ------- + numpy.array + numpy 3x3 array B, with ``B[0]`` as first box vector, + ``B[1]``as second vector, ``B[2]`` as third box vector. - .. note:: + Notes + ----- + The first vector is always pointing along the X-axis, + i.e., parallel to (1, 0, 0). - The first vector is always pointing along the X-axis - i.e. parallel to (1,0,0). .. versionchanged:: 0.7.6 Null-vectors are returned for non-periodic (or missing) unit cell. @@ -231,13 +236,15 @@ def box_volume(dimensions): The volume is computed as `det(x1,x2,x2)` where the xi are the triclinic box vectors from :func:`triclinic_vectors`. - :Arguments: - *dimensions* - list of box lengths and angles (in degrees) such as - [A,B,C,alpha,beta,gamma] + Parameters + ---------- + dimensions : [A, B, C, alpha, beta, gamma] + list of box lengths and angles (in degrees) such as + [A,B,C,alpha,beta,gamma] - :Returns: numpy 3x3 array B, with B[0] = first box vector, - B[1] = second vector, B[2] third box vector. + Returns + ------- + volume : float """ return np.linalg.det(triclinic_vectors(dimensions)) @@ -245,10 +252,12 @@ def box_volume(dimensions): def _is_contiguous(atomgroup, atom): """Walk through atomgroup, starting with atom. - :Returns: - ``True`` if all of *atomgroup* is accessible through walking + Returns + ------- + bool + ``True`` if all of *atomgroup* is accessible through walking along bonds. - ``False`` otherwise. + ``False`` otherwise. """ seen = set([atom]) walked = set() @@ -273,29 +282,7 @@ def _is_contiguous(atomgroup, atom): def make_whole(atomgroup, reference_atom=None): """Move all atoms in a single molecule so that bonds don't split over images - :Arguments: - *atomgroup* - The :class:`MDAnalysis.core.groups.AtomGroup` to work with. - The positions of this are modified in place. All these atoms - must belong in the same molecule or fragment. - - :Keywords: - *reference_atom* - The atom around which all other atoms will be moved. - Defaults to atom 0 in the atomgroup. - - :Returns: - ``None``. Atom positions are modified in place - - :Raises: - `NoDataError` - if there are no bonds present. - (See :func:`~MDAnalysis.topology.core.guess_bonds`) - - `ValueError` - if the algorithm fails to work. This is usually - caused by the atomgroup not being a single fragment. - (ie the molecule can't be traversed by following bonds) + Atoms are modified in place. This function is most useful when atoms have been packed into the primary unit cell, causing breaks mid molecule, with the molecule then appearing @@ -312,29 +299,54 @@ def make_whole(atomgroup, reference_atom=None): | | | | +-----------+ +-----------+ - Usage:: - from MDAnalysis.util.mdamath import make_whole + Parameters + ---------- + atomgroup : AtomGroup + The :class:`MDAnalysis.core.groups.AtomGroup` to work with. + The positions of this are modified in place. All these atoms + must belong in the same molecule or fragment. + reference_atom : :class:`~MDAnalysis.core.groups.Atom` + The atom around which all other atoms will be moved. + Defaults to atom 0 in the atomgroup. + + Raises + ------ + NoDataError + There are no bonds present. + (See :func:`~MDAnalysis.topology.core.guess_bonds`) + + ValueError + The algorithm fails to work. This is usually + caused by the atomgroup not being a single fragment. + (ie the molecule can't be traversed by following bonds) - # This algorithm requires bonds, these can be guessed! - u = mda.Universe(......, guess_bonds=True) + Note + ---- + Only orthogonal boxes are currently supported. + + Example + ------- + Make fragments whole:: - # MDAnalysis can split molecules into their fragments - # based on bonding information. - # Note that this function will only handle a single fragment - # at a time, necessitating a loop. - for frag in u.fragments: + from MDAnalysis.util.mdamath import make_whole + + # This algorithm requires bonds, these can be guessed! + u = mda.Universe(......, guess_bonds=True) + + # MDAnalysis can split molecules into their fragments + # based on bonding information. + # Note that this function will only handle a single fragment + # at a time, necessitating a loop. + for frag in u.fragments: make_whole(frag) Alternatively, to keep a single atom in place as the anchor:: - # This will mean that atomgroup[10] will NOT get moved, - # and all other atoms will move (if necessary). - make_whole(atomgroup, reference_atom=atomgroup[10]) - - .. Note:: + # This will mean that atomgroup[10] will NOT get moved, + # and all other atoms will move (if necessary). + make_whole(atomgroup, reference_atom=atomgroup[10]) - Only orthogonal boxes are currently supported .. versionadded:: 0.11.0 """ @@ -422,22 +434,30 @@ def one_to_many_pointers(Ni, Nj, i2j): Arguments --------- - Ni, Nj - number of i and j components - i2j - the array relating i to parent js + Ni : int + number of i components + Nj : int + number of j components + i2j : numpy.ndarray + relates i to parent js Returns ------- - ordered - an ordered list of i indices [size (i,)] - ptrs - the start and end index for each j [size (Nj, 2)] + ordered : list + an ordered list of i indices [size (i,)] + ptrs : list + the start and end index for each j [size (Nj, 2)] Example ------- - # Residx - the resid of each Atom - ordered, ptrs = one_to_many_pointers(Natoms, Nres, Residx) + .. code:: python + + # Residx - the resid of each Atom + ordered, ptrs = one_to_many_pointers(Natoms, Nres, Residx) + + # Returns an array of the atom indices that are in resid 7 + atoms = ordered[ptrs[7,0]:ptrs[7,1]] - # Returns an array of the atom indices that are in resid 7 - atoms = ordered[ptrs[7,0]:ptrs[7,1]] - """ ordered = i2j.argsort() sorted_idx = i2j[ordered] diff --git a/package/MDAnalysis/lib/qcprot.pyx b/package/MDAnalysis/lib/qcprot.pyx index 885cb3c5365..2d5582bf96c 100644 --- a/package/MDAnalysis/lib/qcprot.pyx +++ b/package/MDAnalysis/lib/qcprot.pyx @@ -93,9 +93,14 @@ matrix [Liu2010]_. A full description of the method, along with the original C implementation can be found at http://theobald.brandeis.edu/qcp/ -.. SeeAlso:: The :func:`CalcRMSDRotationalMatrix` function is used in - :mod:`MDAnalysis.analysis.align` and - :mod:`MDAnalysis.analysis.rmsd`. +See Also +-------- +MDAnalysis.analysis.align: + Align structures using :func:`CalcRMSDRotationalMatrix` +MDAnalysis.analysis.rms.rmsd: + Calculate the RMSD between two structures using + :func:`CalcRMSDRotationalMatrix` + .. versionchanged:: 0.16.0 Call signatures were changed to directly interface with MDAnalysis diff --git a/package/MDAnalysis/lib/util.py b/package/MDAnalysis/lib/util.py index f8d10bb084b..c40c15be7b0 100644 --- a/package/MDAnalysis/lib/util.py +++ b/package/MDAnalysis/lib/util.py @@ -26,6 +26,10 @@ Small helper functions that don't fit anywhere else. +.. versionchanged:: 0.11.0 + Moved mathematical functions into lib.mdamath + + Files and directories --------------------- @@ -147,8 +151,6 @@ close it. -.. versionchanged:: 0.11.0 - Moved mathematical functions into lib.mdamath """ from __future__ import division, absolute_import import six @@ -190,16 +192,18 @@ def callable(obj): def filename(name, ext=None, keep=False): """Return a new name that has suffix attached; replaces other extensions. - :Arguments: - *name* - filename; extension is replaced unless keep=True; - *name* can also be a :class:`NamedStream` (and its - :attr:`NamedStream.name` will be changed accordingly) - *ext* - extension - *keep* - - ``False``: replace existing extension with *ext*; - - ``True``: keep old extension if one existed + Parameters + ---------- + name : str or NamedStream + filename; extension is replaced unless ``keep=True``; + `name` can also be a :class:`NamedStream` (and its + :attr:`NamedStream.name` will be changed accordingly) + ext : None or str + extension to use in the new filename + keep : bool + - ``False``: replace existing extension with `ext`; + - ``True``: keep old extension if one existed + .. versionchanged:: 0.9.0 Also permits :class:`NamedStream` to pass through. @@ -221,10 +225,10 @@ def filename(name, ext=None, keep=False): def openany(datasource, mode='r', reset=True): """Context manager for :func:`anyopen`. - Open the *datasource* and close it when the context of the :keyword:`with` + Open the `datasource` and close it when the context of the :keyword:`with` statement exits. - *datasource* can be a filename or a stream (see :func:`isstream`). A stream + `datasource` can be a filename or a stream (see :func:`isstream`). A stream is reset to its start if possible (via :meth:`~io.IOBase.seek` or :meth:`~cString.StringIO.reset`). @@ -236,10 +240,10 @@ def openany(datasource, mode='r', reset=True): Parameters ---------- datasource : a file or a stream - mode : str - `r` or `w` - reset : bool - try to read (*mode* 'r') the stream from the start [``True``] + mode : {'r', 'w'} (optional) + open in r(ead) or w(rite) mode + reset : bool (optional) + try to read (`mode` 'r') the stream from the start [``True``] Examples -------- @@ -253,7 +257,7 @@ def openany(datasource, mode='r', reset=True): Open a URL and read it:: import urllib2 - with openany(urllib2.urlopen("http://www.MDAnalysis.org/")) as html: + with openany(urllib2.urlopen("http://www.mdanalysis.org/")) as html: print(html.read()) @@ -290,24 +294,28 @@ def bz2_open(filename, mode): def anyopen(datasource, mode='r', reset=True): """Open datasource (gzipped, bzipped, uncompressed) and return a stream. - *datasource* can be a filename or a stream (see :func:`isstream`). By + `datasource` can be a filename or a stream (see :func:`isstream`). By default, a stream is reset to its start if possible (via :meth:`~io.IOBase.seek` or :meth:`~cString.StringIO.reset`). If possible, the attribute ``stream.name`` is set to the filename or "" if no filename could be associated with the *datasource*. - :Arguments: - *datasource* + Parameters + ---------- + datasource a file (from :class:`file` or :func:`open`) or a stream (e.g. from :func:`urllib2.urlopen` or :class:`cStringIO.StringIO`) - *mode* - 'r' or 'w' or 'a', more complicated modes ('r+', 'w+' are not supported because - only the first letter is looked at) [``'r'``] - *reset* - try to read (*mode* 'r') the stream from the start [``True``] + mode: {'r', 'w', 'a'} (optional) + Open in r(ead), w(rite) or a(ppen) mode. More complicated + modes ('r+', 'w+', ...) are not supported; only the first letter of + `mode` is used and thus any additional modifiers are silently ignored. + reset: bool (optional) + try to read (`mode` 'r') the stream from the start - :Returns: tuple ``stream`` which is a file-like object + Returns + ------- + file-like object See Also -------- @@ -318,6 +326,7 @@ def anyopen(datasource, mode='r', reset=True): .. versionchanged:: 0.9.0 Only returns the ``stream`` and tries to set ``stream.name = filename`` instead of the previous behavior to return a tuple ``(stream, filename)``. + """ handlers = {'bz2': bz2_open, 'gz': gzip.open, '': open} @@ -411,18 +420,21 @@ def greedy_splitext(p): Arguments --------- - p : path, string + p : str + path Returns ------- - Tuple ``(root, extension)`` where ``root`` is the full path and - filename with all extensions removed whereas ``extension`` is the - string of all extensions. + (root, extension) : tuple + where ``root`` is the full path and filename with all + extensions removed whereas ``extension`` is the string of + all extensions. Example ------- >>> greedy_splitext("/home/joe/protein.pdb.bz2") ('/home/joe/protein', '.pdb.bz2') + """ path, root = os.path.split(p) extension = '' @@ -440,7 +452,7 @@ def hasmethod(obj, m): def isstream(obj): - """Detect if *obj* is a stream. + """Detect if `obj` is a stream. We consider anything a stream that has the methods @@ -451,17 +463,20 @@ def isstream(obj): - ``read()``, ``readline()``, ``readlines()`` - ``write()``, ``writeline()``, ``writelines()`` + Parameters + ---------- + obj : stream or str + + Returns + ------- + bool + ``True`` if `obj` is a stream, ``False`` otherwise + See Also -------- :mod:`io` - :Arguments: - *obj* - stream or string - - :Returns: ``True`` is *obj* is a stream, ``False`` otherwise - .. versionadded:: 0.9.0 """ signature_methods = ("close",) @@ -481,9 +496,20 @@ def isstream(obj): def which(program): - """Determine full path of executable *program* on :envvar:`PATH`. + """Determine full path of executable `program` on :envvar:`PATH`. (Jay at http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python) + + Parameters + ---------- + programe : str + name of the executable + + Returns + ------- + path : str or None + absolute path to the executable if it can be found, else ``None`` + """ def is_exe(fpath): @@ -506,7 +532,7 @@ def is_exe(fpath): class NamedStream(io.IOBase): """Stream that also provides a (fake) name. - By wrapping a stream *stream* in this class, it can be passed to + By wrapping a stream `stream` in this class, it can be passed to code that uses inspection of the filename to make decisions. For instance. :func:`os.path.split` will work correctly on a :class:`NamedStream`. @@ -520,8 +546,8 @@ class NamedStream(io.IOBase): and :func:`os.path.expanduser`, which will return the :class:`NamedStream` itself instead of a string if no substitutions were made. - .. rubric:: Example - + Example + ------- Wrap a :func:`cStringIO.StringIO` instance to write to:: import cStringIO @@ -544,26 +570,26 @@ class NamedStream(io.IOBase): # ... print f.closed # --> True - .. Note:: - - This class uses its own :meth:`__getitem__` method so if *stream* - implements :meth:`stream.__getitem__` then that will be masked and this - class should not be used. - - .. Warning:: + Note + ---- + This class uses its own :meth:`__getitem__` method so if `stream` + implements :meth:`stream.__getitem__` then that will be masked and + this class should not be used. - By default, :meth:`NamedStream.close` will **not close the - stream** but instead :meth:`~NamedStream.reset` it to the - beginning. [#NamedStreamClose]_ Provide the ``force=True`` keyword - to :meth:`NamedStream.close` to always close the stream. + Warning + ------- + By default, :meth:`NamedStream.close` will **not close the + stream** but instead :meth:`~NamedStream.reset` it to the + beginning. [#NamedStreamClose]_ Provide the ``force=True`` keyword + to :meth:`NamedStream.close` to always close the stream. """ def __init__(self, stream, filename, reset=True, close=False): - """Initialize the :class:`NamedStream` from a *stream* and give it a *name*. + """Initialize the :class:`NamedStream` from a `stream` and give it a `name`. The constructor attempts to rewind the stream to the beginning unless - the keyword *reset* is set to ``False``. If rewinding fails, a + the keyword `reset` is set to ``False``. If rewinding fails, a :class:`MDAnalysis.StreamWarning` is issued. Parameters @@ -572,10 +598,10 @@ def __init__(self, stream, filename, reset=True, close=False): an open stream (e.g. :class:`file` or :func:`cStringIO.StringIO`) filename : str the filename that should be associated with the stream - reset : bool + reset : bool (optional) start the stream from the beginning (either :meth:`reset` or :meth:`seek`) when the class instance is constructed - close : bool + close : bool (optional) close the stream when a :keyword:`with` block exits or when :meth:`close` is called; note that the default is **not to close the stream** @@ -669,19 +695,28 @@ def closed(self): return super(NamedStream, self).closed def seek(self, offset, whence=os.SEEK_SET): - """Change the stream position to the given byte *offset* . - - *offset* is interpreted relative to the position indicated by - *whence*. Values for *whence* are: + """Change the stream position to the given byte `offset` . - - :data:`io.SEEK_SET` or 0 – start of the stream (the default); *offset* - should be zero or positive - - :data:`io.SEEK_CUR` or 1 – current stream position; *offset* may be - negative - - :data:`io.SEEK_END` or 2 – end of the stream; *offset* is usually - negative + Parameters + ---------- + offset : int + `offset` is interpreted relative to the position + indicated by `whence`. + whence : {0, 1, 2} (optional) + Values for `whence` are: + + - :data:`io.SEEK_SET` or 0 – start of the stream (the default); `offset` + should be zero or positive + - :data:`io.SEEK_CUR` or 1 – current stream position; `offset` may be + negative + - :data:`io.SEEK_END` or 2 – end of the stream; `offset` is usually + negative + + Returns + ------- + int + the new absolute position in bytes. - :Returns: the new absolute position. """ try: return self.stream.seek(offset, whence) # file.seek: no kw @@ -696,10 +731,14 @@ def tell(self): return super(NamedStream, self).tell() def truncate(self, *size): - """Truncate the stream's size to *size*. + """Truncate the stream's size to `size`. + + Parameters + ---------- + size : int (optional) + The `size` defaults to the current position (if no `size` argument + is supplied). The current file position is not changed. - The size defaults to the current position (if no *size* argument is - supplied). The current file position is not changed. """ try: return self.stream.truncate(*size) @@ -709,7 +748,9 @@ def truncate(self, *size): def seekable(self): """Return ``True`` if the stream supports random access. - If ``False``, :meth:`seek`, :meth:`tell` and :meth:`truncate` will raise :exc:`IOError`. + If ``False``, :meth:`seek`, :meth:`tell` and :meth:`truncate` will + raise :exc:`IOError`. + """ try: return self.stream.seekable() @@ -798,9 +839,9 @@ def __repr__(self): def realpath(*args): - """Join all args and return the real path, rooted at /. + """Join all args and return the real path, rooted at ``/``. - Expands '~', '~user', and environment variables such as :envvar`$HOME`. + Expands '~', '~user', and environment variables such as :envvar:`$HOME`. Returns ``None`` if any of the args is ``None``. """ @@ -810,9 +851,16 @@ def realpath(*args): def get_ext(filename): - """Return the lower-cased extension of *filename* without a leading dot. + """Return the lower-cased extension of `filename` without a leading dot. + + Parameters + ---------- + filename : str - :Returns: root, ext + Returns + ------- + root : str + ext : str """ root, ext = os.path.splitext(filename) if ext.startswith(os.extsep): @@ -821,7 +869,27 @@ def get_ext(filename): def check_compressed_format(root, ext): - """Check if this is a supported gzipped/bzip2ed file format and return UPPERCASE format.""" + """Check if this is a supported gzipped/bzip2ed file format and return UPPERCASE format. + + Parameters + ---------- + root : str + path of a file, without extension `ext` + ext : str + extension (currently only "bz2" and "gz" are recognized as compressed formats) + + Returns + ------- + format : str + upper case format extension *if* the compression can be handled by + :func:`openany` + + See Also + -------- + openany : function that is used to open and decompress formats on the fly; only + compression formats implemented in :func:`openany` are recognized + + """ # XYZReader&others are setup to handle both plain and compressed (bzip2, gz) files # ..so if the first file extension is bzip2 or gz, look at the one to the left of it if ext.lower() in ("bz2", "gz"): @@ -835,7 +903,21 @@ def check_compressed_format(root, ext): def format_from_filename_extension(filename): - """Guess file format from the file extension""" + """Guess file format from the file extension. + + Parameters + ---------- + filename : str + + Returns + ------- + format : str + + Raises + ------ + TypeError + if the file format cannot be determined + """ try: root, ext = get_ext(filename) except: @@ -848,19 +930,31 @@ def format_from_filename_extension(filename): def guess_format(filename): - """Return the format of *filename* + """Return the format of `filename` + + The current heuristic simply looks at the filename extension and can work + around compressed format extensions. + + Parameters + ---------- + filename : str or stream + path to the file or a stream, in which case ``filename.name`` is looked + at for a hint to the format - The current heuristic simply looks at the filename extension - and can work around compressed format extensions + Returns + ------- + format : str + format specifier (upper case) - *filename* can also be a stream, in which case - *filename.name* is looked at for a hint to the format + Raises + ------ + ValueError + if the heuristics are insufficient to guess a supported format - :Raises: - *ValueError* .. versionadded:: 0.11.0 Moved into lib.util + """ if isstream(filename): # perhaps StringIO or open stream @@ -882,7 +976,7 @@ def guess_format(filename): def iterable(obj): - """Returns ``True`` if *obj* can be iterated over and is *not* a string + """Returns ``True`` if `obj` can be iterated over and is *not* a string nor a :class:`NamedStream`""" if isinstance(obj, (six.string_types, NamedStream)): return False # avoid iterating over characters of a string @@ -897,7 +991,16 @@ def iterable(obj): def asiterable(obj): - """Returns obj so that it can be iterated over; a string is *not* treated as iterable""" + """Returns `obj` so that it can be iterated over. + + A string is *not* detected as and iterable and is wrapped into a :class:`list` + with a single element. + + See Also + -------- + iterable + + """ if not iterable(obj): obj = [obj] return obj @@ -911,7 +1014,7 @@ def asiterable(obj): def strip(s): - """Convert *s* to a string and return it white-space stripped.""" + """Convert `s` to a string and return it white-space stripped.""" return str(s).strip() @@ -925,12 +1028,13 @@ class FixedcolumnEntry(object): def __init__(self, start, stop, typespecifier): """ - :Arguments: - *start* + Parameters + ---------- + start : int first column - *stop* + stop : int last column + 1 - *typespecifier* + typespecifier : str 'I': int, 'F': float, 'E': float, 'A': stripped string The start/stop arguments follow standard Python convention in that @@ -942,7 +1046,7 @@ def __init__(self, start, stop, typespecifier): self.convertor = self.convertors[typespecifier] def read(self, line): - """Read the entry from *line* and convert to appropriate type.""" + """Read the entry from `line` and convert to appropriate type.""" try: return self.convertor(line[self.start:self.stop]) except ValueError: @@ -959,13 +1063,8 @@ def __repr__(self): class FORTRANReader(object): """FORTRANReader provides a method to parse FORTRAN formatted lines in a file. - Usage:: - - atomformat = FORTRANReader('2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10') - for line in open('coordinates.crd'): - serial,TotRes,resName,name,x,y,z,chainID,resSeq,tempFactor = atomformat.read(line) - - Fortran format edit descriptors; see `Fortran Formats`_ for the syntax. + The contents of lines in a file can be parsed according to FORTRAN format + edit descriptors (see `Fortran Formats`_ for the syntax). Only simple one-character specifiers supported here: *I F E A X* (see :data:`FORTRAN_format_regex`). @@ -975,12 +1074,28 @@ class FORTRANReader(object): .. _`Fortran Formats`: http://www.webcitation.org/5xbaWMV2x .. _`Fortran Formats (URL)`: http://www.cs.mtu.edu/~shene/COURSES/cs201/NOTES/chap05/format.html + """ def __init__(self, fmt): """Set up the reader with the FORTRAN format string. - The string *fmt* should look like '2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10'. + The string `fmt` should look like '2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10'. + + Parameters + ---------- + fmt : str + FORTRAN format edit descriptor for a line as described in `Fortran + Formats`_ + + Example + ------- + Parsing of a standard CRD file:: + + atomformat = FORTRANReader('2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10') + for line in open('coordinates.crd'): + serial,TotRes,resName,name,x,y,z,chainID,resSeq,tempFactor = atomformat.read(line) + """ self.fmt = fmt.split(',') descriptors = [self.parse_FORTRAN_format(descriptor) for descriptor in self.fmt] @@ -996,13 +1111,23 @@ def __init__(self, fmt): start += d['totallength'] def read(self, line): - """Parse *line* according to the format string and return list of values. + """Parse `line` according to the format string and return list of values. Values are converted to Python types according to the format specifier. - :Returns: list of entries with appropriate types - :Raises: :exc:`ValueError` if any of the conversions cannot be made - (e.g. space for an int) + Parameters + ---------- + line : str + + Returns + ------- + list + list of entries with appropriate types + + Raises + ------ + ValueError + Any of the conversions cannot be made (e.g. space for an int) See Also -------- @@ -1025,18 +1150,27 @@ def number_of_matches(self, line): def parse_FORTRAN_format(self, edit_descriptor): """Parse the descriptor. - parse_FORTRAN_format(edit_descriptor) --> dict - :Returns: dict with totallength (in chars), repeat, length, - format, decimals - :Raises: :exc:`ValueError` if the *edit_descriptor* is not recognized - and cannot be parsed + Parameters + ---------- + edit_descriptor : str + FORTRAN format edit descriptor + + Returns + ------- + dict + dict with totallength (in chars), repeat, length, format, decimals - .. Note:: + Raises + ------ + ValueError + The `edit_descriptor` is not recognized and cannot be parsed + + Note + ---- + Specifiers: *L ES EN T TL TR / r S SP SS BN BZ* are *not* supported, + and neither are the scientific notation *Ew.dEe* forms. - Specifiers: *L ES EN T TL TR / r S SP SS BN BZ* are *not* - supported, and neither are the scientific notation *Ew.dEe* - forms. """ m = _FORTRAN_format_pattern.match(edit_descriptor.upper()) @@ -1071,11 +1205,38 @@ def __repr__(self): def fixedwidth_bins(delta, xmin, xmax): - """Return bins of width delta that cover xmin,xmax (or a larger range). + """Return bins of width `delta` that cover `xmin`, `xmax` (or a larger range). + + The bin parameters are computed such that the bin size `delta` is + guaranteed. In order to achieve this, the range `[xmin, xmax]` can be + increased. - dict = fixedwidth_bins(delta,xmin,xmax) + Bins can be calculated for 1D data (then all parameters are simple floats) + or nD data (then parameters are supplied as arrays, with each entry + correpsonding to one dimension). + + Parameters + ---------- + delta : float or array_like + desired spacing of the bins + xmin : float or array_like + lower bound (left boundary of first bin) + xmax : float or array_like + upper bound (right boundary of last bin) + + Returns + ------- + dict + The dict contains 'Nbins', 'delta', 'min', and 'max'; these are either + floats or arrays, depending on the input. + + Example + ------- + Use with :func:`numpy.histogram`:: + + B = fixedwidth_bins(delta, xmin, xmax) + h, e = np.histogram(data, bins=B['Nbins'], range=(B['min'], B['max'])) - The dict contains 'Nbins', 'delta', 'min', and 'max'. """ if not np.all(xmin < xmax): raise ValueError('Boundaries are not sane: should be xmin < xmax.') @@ -1124,6 +1285,21 @@ def fixedwidth_bins(delta, xmin, xmax): def convert_aa_code(x): """Converts between 3-letter and 1-letter amino acid codes. + Parameters + ---------- + x : str + 1-letter or 3-letter amino acid code + + Returns + ------- + str + 3-letter or 1-letter amino acid code + + Raises + ------ + ValueError + No conversion can be made; the amino acid code is not defined. + Note ---- Data are defined in :data:`amino_acid_codes` and :data:`inverse_aa_codes`. @@ -1160,21 +1336,29 @@ def convert_aa_code(x): def parse_residue(residue): """Process residue string. - Examples: + Parameters + ---------- + residue: str + The *residue* must contain a 1-letter or 3-letter or + 4-letter residue string, a number (the resid) and + optionally an atom identifier, which must be separate + from the residue with a colon (":"). White space is + allowed in between. + + Returns + ------- + tuple + `(3-letter aa string, resid, atomname)`; known 1-letter + aa codes are converted to 3-letter codes + + Examples + -------- - "LYS300:HZ1" --> ("LYS", 300, "HZ1") - "K300:HZ1" --> ("LYS", 300, "HZ1") - "K300" --> ("LYS", 300, None) - "4GB300:H6O" --> ("4GB", 300, "H6O") - "4GB300" --> ("4GB", 300, None) - :Argument: The *residue* must contain a 1-letter or 3-letter or - 4-letter residue string, a number (the resid) and - optionally an atom identifier, which must be separate - from the residue with a colon (":"). White space is - allowed in between. - - :Returns: `(3-letter aa string, resid, atomname)`; known 1-letter - aa codes are converted to 3-letter codes """ # XXX: use _translate_residue() .... @@ -1192,7 +1376,7 @@ def parse_residue(residue): def conv_float(s): - """Convert an object *s* to float if possible. + """Convert an object `s` to float if possible. Function to be passed into :func:`map` or a list comprehension. If the argument can be interpreted as a float it is converted, @@ -1205,11 +1389,14 @@ def conv_float(s): def cached(key): - """Cache a property within a class + """Cache a property within a class. Requires the Class to have a cache dict called ``_cache``. - Usage:: + Example + ------- + How to add a cache for a variable to a class by using the `@cached` + decorator:: class A(object): def__init__(self): @@ -1223,7 +1410,9 @@ def size(self): # _cache with the key: 'keyname' size = 10.0 + .. versionadded:: 0.9.0 + """ def cached_lookup(func): @@ -1247,11 +1436,15 @@ def unique_rows(arr, return_index=False): --------- arr : np.array of shape (n1, m) return_index : bool, optional - If True, returns indices of arr that formed answer (see np.unique) + If ``True``, returns indices of array that formed answer (see + :func:`numpy.unique`) Returns ------- - unique_rows (n2, m) + unique_rows : numpy.array + shape (n2, m) + r_idx : numpy.array (optional) + index (if `return_index` was ``True``) Examples -------- @@ -1260,6 +1453,11 @@ def unique_rows(arr, return_index=False): >>> b = unique_rows(a) >>> b array([[0, 1], [1, 2], [2, 3]]) + + See Also + -------- + numpy.unique + """ # From here, but adapted to handle any size rows # https://mail.scipy.org/pipermail/scipy-user/2011-December/031200.html @@ -1269,7 +1467,7 @@ def unique_rows(arr, return_index=False): # eg: idx = np.array([1, 2])[None, :] if not arr.flags['OWNDATA']: arr = arr.copy() - + m = arr.shape[1] if return_index: @@ -1296,15 +1494,15 @@ def blocks_of(a, n, m): m : int size of block in second dimension - Returns ------- - (nblocks, n, m) view of the original array. - Where nblocks is the number of times the miniblock fits in the original. + (nblocks, n, m) : tuple + view of the original array, where nblocks is the number of times the + miniblock fits in the original. Raises ------ - ValueError + ValueError If the supplied `n` and `m` don't divide `a` into an integer number of blocks. @@ -1321,13 +1519,15 @@ def blocks_of(a, n, m): Notes ----- - n, m must divide a into an identical integer number of blocks. + n, m must divide a into an identical integer number of blocks. - Uses strides so probably requires that the array is C contiguous + Uses strides so probably requires that the array is C contiguous. + + Returns a view, so editing this modifies the original array. - Returns a view, so editing this modifies the original array .. versionadded:: 0.12.0 + """ # based on: # http://stackoverflow.com/a/10862636 diff --git a/package/MDAnalysis/topology/GROParser.py b/package/MDAnalysis/topology/GROParser.py index 60758b0c41d..d2943528d74 100644 --- a/package/MDAnalysis/topology/GROParser.py +++ b/package/MDAnalysis/topology/GROParser.py @@ -34,6 +34,7 @@ :mod:`MDAnalysis.coordinates.GRO` + Classes ------- @@ -132,7 +133,7 @@ def parse(self): # Guess types and masses atomtypes = guessers.guess_types(names) masses = guessers.guess_masses(atomtypes) - + residx, (new_resids, new_resnames) = change_squash( (resids, resnames), (resids, resnames)) diff --git a/package/MDAnalysis/topology/PDBQTParser.py b/package/MDAnalysis/topology/PDBQTParser.py index c87c479ecb1..4ce2f342d62 100644 --- a/package/MDAnalysis/topology/PDBQTParser.py +++ b/package/MDAnalysis/topology/PDBQTParser.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors diff --git a/package/MDAnalysis/topology/PQRParser.py b/package/MDAnalysis/topology/PQRParser.py index df87e3c6f37..a6c4bc20d0f 100644 --- a/package/MDAnalysis/topology/PQRParser.py +++ b/package/MDAnalysis/topology/PQRParser.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 --- http://www.mdanalysis.org # Copyright (c) 2006-2016 The MDAnalysis Development Team and contributors diff --git a/package/MDAnalysis/topology/TPRParser.py b/package/MDAnalysis/topology/TPRParser.py index 616d7cd0172..f31c8df88ae 100644 --- a/package/MDAnalysis/topology/TPRParser.py +++ b/package/MDAnalysis/topology/TPRParser.py @@ -202,7 +202,7 @@ def parse(self): raise IOError(msg) tpr_top.add_TopologyAttr(Resnums(tpr_top.resids.values.copy())) - + return tpr_top # THE FOLLOWING CODE IS WORKING FOR TPX VERSION 58, BUT SINCE THESE INFO IS diff --git a/package/MDAnalysis/topology/guessers.py b/package/MDAnalysis/topology/guessers.py index d349ce027e3..06dd9a16d2b 100644 --- a/package/MDAnalysis/topology/guessers.py +++ b/package/MDAnalysis/topology/guessers.py @@ -79,11 +79,13 @@ def guess_atom_type(atomname): At the moment, this function simply returns the element, as guessed by :func:`guess_atom_element`. + See Also -------- :func:`guess_atom_element` :mod:`MDAnalysis.topology.tables` + """ return guess_atom_element(atomname) @@ -245,8 +247,10 @@ def guess_angles(bonds): Returns ------- - List of tuples defining the angles. - Suitable for use in u._topology + list of tuples + List of tuples defining the angles. + Suitable for use in u._topology + See Also -------- @@ -277,9 +281,11 @@ def guess_dihedrals(angles): Works by assuming that if (1,2,3) is an angle, and 3 & 4 are bonded, then (1,2,3,4) must be a dihedral. - :Returns: - List of tuples defining the dihedrals. - Suitable for use in u._topology + Returns + ------- + list of tuples + List of tuples defining the dihedrals. + Suitable for use in u._topology .. versionadded 0.9.0 """ @@ -311,9 +317,10 @@ def guess_improper_dihedrals(angles): ie the improper dihedral is the angle between the planes formed by (1, 2, 3) and (1, 3, 4) - :Returns: - List of tuples defining the improper dihedrals. - Suitable for use in u._topology + Returns + ------- + List of tuples defining the improper dihedrals. + Suitable for use in u._topology .. versionadded 0.9.0 """ diff --git a/package/MDAnalysis/units.py b/package/MDAnalysis/units.py index a26f2f6dc28..8429d456ae6 100644 --- a/package/MDAnalysis/units.py +++ b/package/MDAnalysis/units.py @@ -114,7 +114,8 @@ Note ---- -Maybe we should simply use Quantities_ or :mod:`scipy.constants`? +In the future me might move towards using the Quantities_ package or +:mod:`scipy.constants`. .. _Quantities: http://packages.python.org/quantities/ @@ -347,11 +348,16 @@ def get_conversion_factor(unit_type, u1, u2): def convert(x, u1, u2): """Convert value *x* in unit *u1* to new value in *u2*. - :Returns: Converted value. + Returns + ------- + float + Converted value. - :Raises: :Exc:`ValueError` if the units are not known or if - one attempts to convert between incompatible - units. + Raises + ------ + ValueError + The units are not known or if one attempts to convert between + incompatible units. """ try: ut1 = unit_types[u1] diff --git a/package/doc/sphinx/Makefile b/package/doc/sphinx/Makefile index 204cca34d64..071a744aab0 100644 --- a/package/doc/sphinx/Makefile +++ b/package/doc/sphinx/Makefile @@ -3,7 +3,7 @@ # You can set these variables from the command line. SPHINXOPTS = -SPHINXBUILD = sphinx-build +SPHINXBUILD = sphinx-build -v -W PAPER = BUILDDIR = .. diff --git a/package/doc/sphinx/source/documentation_pages/coordinates/GRO.rst b/package/doc/sphinx/source/documentation_pages/coordinates/GRO.rst index 73a18a09f59..5031c40fe32 100644 --- a/package/doc/sphinx/source/documentation_pages/coordinates/GRO.rst +++ b/package/doc/sphinx/source/documentation_pages/coordinates/GRO.rst @@ -1,2 +1,2 @@ .. automodule:: MDAnalysis.coordinates.GRO - :members: +