Ejemplo n.º 1
0
 def test_usage_1(self):
     ret = util.fixedwidth_bins(0.1, 4.0, 5.0)
     assert ret['Nbins'] == 10
     assert ret['delta'] == 0.1
     assert ret['min'] == 4.0
     assert ret['max'] == 5.0
Ejemplo n.º 2
0
 def test_usage_2(self):
     ret = util.fixedwidth_bins(0.4, 4.0, 5.0)
     assert ret['Nbins'] == 3
     assert ret['delta'] == 0.4
     assert_almost_equal(ret['min'], 3.9)
     assert_almost_equal(ret['max'], 5.1)
Ejemplo n.º 3
0
 def test_usage_2(self):
     ret = util.fixedwidth_bins(0.4, 4.0, 5.0)
     assert ret['Nbins'] == 3
     assert ret['delta'] == 0.4
     assert_almost_equal(ret['min'], 3.9)
     assert_almost_equal(ret['max'], 5.1)
Ejemplo n.º 4
0
 def test_keys(self):
     ret = util.fixedwidth_bins(0.5, 1.0, 2.0)
     for k in ['Nbins', 'delta', 'min', 'max']:
         assert k in ret
Ejemplo n.º 5
0
def density_from_Universe(universe,
                          delta=1.0,
                          atomselection='name OH2',
                          start=None,
                          stop=None,
                          step=None,
                          metadata=None,
                          padding=2.0,
                          cutoff=0,
                          soluteselection=None,
                          use_kdtree=True,
                          update_selection=False,
                          quiet=False,
                          interval=1,
                          **kwargs):
    """Create a density grid from a :class:`MDAnalysis.Universe` object.

    The trajectory is read, frame by frame, and the atoms selected with *atomselection* are
    histogrammed on a grid with spacing *delta*::

      density_from_Universe(universe, delta=1.0, atomselection='name OH2', ...) --> density

    .. Note:: By default, the *atomselection* is static, i.e., atoms are only
              selected once at the beginning. If you want dynamically changing
              selections (such as "name OW and around 4.0 (protein and not name
              H*)") then set ``update_selection=True``. For the special case of
              calculating a density of the "bulk" solvent away from a solute
              use the optimized selections with keywords *cutoff* and
              *soluteselection*.

    :Arguments:
      universe
            :class:`MDAnalysis.Universe` object with a trajectory

    :Keywords:
      atomselection
            selection string (MDAnalysis syntax) for the species to be analyzed
            ["name OH2"]
      delta
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
      start, stop, step
            Slice the trajectory as ``trajectory[start"stop:step]``; default
            is to read the whole trajectory.
      metadata
            dictionary of additional data to be saved with the object
      padding
            increase histogram dimensions by padding (on top of initial box size)
            in Angstroem [2.0]
      soluteselection
            MDAnalysis selection for the solute, e.g. "protein" [``None``]
      cutoff
            With *cutoff*, select "<atomsel> NOT WITHIN <cutoff> OF <soluteselection>"
            (Special routines that are faster than the standard ``AROUND`` selection)
            [0]
      update_selection
            Should the selection of atoms be updated for every step? [``False``]
            - ``True``: atom selection is updated for each frame, can be slow
            - ``False``: atoms are only selected at the beginning
      quiet
            Print status update to the screen for every *interval* frame? [``False``]
            - ``True``: no status updates when a new frame is processed
            - ``False``: status update every frame (including number of atoms
              processed, which is interesting with ``update_selection=True``)
      interval
           Show status update every *interval* frame [1]
      parameters
            dict with some special parameters for :class:`Density` (see doc)
      kwargs
            metadata, parameters are modified and passed on to :class:`Density`

    :Returns: :class:`Density`

    .. versionchanged:: 0.13.0
       *update_selection* and *quite* keywords added

    """
    try:
        universe.select_atoms('all')
        universe.trajectory.ts
    except AttributeError:
        raise TypeError(
            "The universe must be a proper MDAnalysis.Universe instance.")
    u = universe
    if cutoff > 0 and soluteselection is not None:
        # special fast selection for '<atomsel> not within <cutoff> of <solutesel>'
        notwithin_coordinates = notwithin_coordinates_factory(
            u, atomselection, soluteselection, cutoff, use_kdtree=use_kdtree)

        def current_coordinates():
            return notwithin_coordinates()
    else:
        group = u.select_atoms(atomselection)

        def current_coordinates():
            return group.coordinates()

    coord = current_coordinates()
    logger.info(
        "Selected {0:d} atoms out of {1:d} atoms ({2!s}) from {3:d} total.".
        format(coord.shape[0], len(u.select_atoms(atomselection)),
               atomselection, len(u.atoms)))

    # mild warning; typically this is run on RMS-fitted trajectories and
    # so the box information is rather meaningless
    box, angles = u.trajectory.ts.dimensions[:3], u.trajectory.ts.dimensions[
        3:]
    if tuple(angles) != (90., 90., 90.):
        msg = "Non-orthorhombic unit-cell --- make sure that it has been remapped properly!"
        warnings.warn(msg)
        logger.warn(msg)

    # Make the box bigger to avoid as much as possible 'outlier'. This
    # is important if the sites are defined at a high density: in this
    # case the bulk regions don't have to be close to 1 * n0 but can
    # be less. It's much more difficult to deal with outliers.  The
    # ideal solution would use images: implement 'looking across the
    # periodic boundaries' but that gets complicate when the box
    # rotates due to RMS fitting.
    smin = np.min(coord, axis=0) - padding
    smax = np.max(coord, axis=0) + padding

    BINS = fixedwidth_bins(delta, smin, smax)
    arange = zip(BINS['min'], BINS['max'])
    bins = BINS['Nbins']

    # create empty grid with the right dimensions (and get the edges)
    grid, edges = np.histogramdd(np.zeros((1, 3)),
                                 bins=bins,
                                 range=arange,
                                 normed=False)
    grid *= 0.0
    h = grid.copy()

    pm = ProgressMeter(u.trajectory.n_frames,
                       interval=interval,
                       quiet=quiet,
                       format="Histogramming %(n_atoms)6d atoms in frame "
                       "%(step)5d/%(numsteps)d  [%(percentage)5.1f%%]\r")
    for ts in u.trajectory[start:stop:step]:
        if update_selection:
            group = u.select_atoms(atomselection)
            coord = group.positions
        else:
            coord = current_coordinates()

        pm.echo(ts.frame, n_atoms=len(coord))
        if len(coord) == 0:
            continue

        h[:], edges[:] = np.histogramdd(coord,
                                        bins=bins,
                                        range=arange,
                                        normed=False)
        grid += h  # accumulate average histogram
    n_frames = u.trajectory.n_frames
    grid /= float(n_frames)

    # pick from kwargs
    metadata = kwargs.pop('metadata', {})
    metadata['psf'] = u.filename
    metadata['dcd'] = u.trajectory.filename
    metadata['atomselection'] = atomselection
    metadata['n_frames'] = n_frames
    metadata['totaltime'] = round(u.trajectory.n_frames * u.trajectory.dt, 3)
    metadata['dt'] = u.trajectory.dt
    metadata['time_unit'] = MDAnalysis.core.flags['time_unit']
    try:
        metadata['trajectory_skip'] = u.trajectory.skip_timestep  # frames
    except AttributeError:
        metadata['trajectory_skip'] = 1  # seems to not be used..
    try:
        metadata['trajectory_delta'] = u.trajectory.delta  # in native units
    except AttributeError:
        metadata['trajectory_delta'] = 1
    if cutoff > 0 and soluteselection is not None:
        metadata['soluteselection'] = soluteselection
        metadata['cutoff'] = cutoff  # in Angstrom

    parameters = kwargs.pop('parameters', {})
    parameters['isDensity'] = False  # must override

    # all other kwargs are discarded

    g = Density(grid=grid,
                edges=edges,
                units={'length': MDAnalysis.core.flags['length_unit']},
                parameters=parameters,
                metadata=metadata)
    g.make_density()
    logger.info("Density completed (initial density in Angstrom**-3)")

    return g
Ejemplo n.º 6
0
 def test_usage_1(self):
     ret = util.fixedwidth_bins(0.1, 4.0, 5.0)
     assert ret['Nbins'] == 10
     assert ret['delta'] == 0.1
     assert ret['min'] == 4.0
     assert ret['max'] == 5.0
Ejemplo n.º 7
0
def density_from_Universe(universe,
                          delta=1.0,
                          atomselection='name OH2',
                          start=None,
                          stop=None,
                          step=None,
                          metadata=None,
                          padding=2.0,
                          cutoff=0,
                          soluteselection=None,
                          use_kdtree=True,
                          update_selection=False,
                          verbose=None,
                          interval=1,
                          quiet=None,
                          parameters=None):
    """Create a density grid from a :class:`MDAnalysis.Universe` object.

    The trajectory is read, frame by frame, and the atoms selected with `atomselection` are
    histogrammed on a grid with spacing `delta`.

    Parameters
    ----------
    universe : MDAnalysis.Universe
            :class:`MDAnalysis.Universe` object with a trajectory
    atomselection : str (optional)
            selection string (MDAnalysis syntax) for the species to be analyzed
            ["name OH2"]
    delta : float (optional)
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
    start : int (optional)
    stop : int (optional)
    step : int (optional)
            Slice the trajectory as ``trajectory[start:stop:step]``; default
            is to read the whole trajectory.
    metadata : dict. optional
            `dict` of additional data to be saved with the object; the meta data
            are passed through as they are.
    padding : float (optional)
            increase histogram dimensions by padding (on top of initial box size)
            in Angstroem [2.0]
    soluteselection : str (optional)
            MDAnalysis selection for the solute, e.g. "protein" [``None``]
    cutoff : float (optional)
            With `cutoff`, select "<atomsel> NOT WITHIN <cutoff> OF <soluteselection>"
            (Special routines that are faster than the standard ``AROUND`` selection);
            any value that evaluates to ``False`` (such as the default 0) disables this
            special selection.
    update_selection : bool (optional)
            Should the selection of atoms be updated for every step? [``False``]

            - ``True``: atom selection is updated for each frame, can be slow
            - ``False``: atoms are only selected at the beginning
    verbose : bool (optional)
            Print status update to the screen for every *interval* frame? [``True``]

            - ``False``: no status updates when a new frame is processed
            - ``True``: status update every frame (including number of atoms
              processed, which is interesting with ``update_selection=True``)
    interval : int (optional)
           Show status update every `interval` frame [1]
    parameters : dict (optional)
            `dict` with some special parameters for :class:`Density` (see docs)

    Returns
    -------
    :class:`Density`
            A :class:`Density` instance with the histogrammed data together
            with associated metadata.


    Notes
    -----

    By default, the `atomselection` is static, i.e., atoms are only selected
    once at the beginning. If you want *dynamically changing selections* (such
    as "name OW and around 4.0 (protein and not name H*)", i.e., the water
    oxygen atoms that are within 4 Å of the protein heavy atoms) then set
    ``update_selection=True``. For the special case of calculating a density of
    the "bulk" solvent away from a solute use the optimized selections with
    keywords *cutoff* and *soluteselection* (see Examples below).

    Examples
    --------
    Basic use for creating a water density (just using the water oxygen atoms "OW")::

      density = density_from_Universe(universe, delta=1.0, atomselection='name OW')

    If you are only interested in water within a certain region, e.g., within a
    vicinity around a binding site, you can use a selection that updates every
    step by setting the `update_selection` keyword argument::

      site_density = density_from_Universe(universe, delta=1.0,
                                           atomselection='name OW and around 5 (resid 156 157 305)',
                                           update_selection=True)

    A special case for an updating selection is to create the "bulk density",
    i.e., the water outside the immediate solvation shell of a protein: Select
    all water oxygen atoms that are *farther away* than a given cut-off (say, 4
    Å) from the solute (here, heavy atoms of the protein)::

      bulk = density_from_Universe(universe, delta=1.0, atomselection='name OW',
                                   solute="protein and not name H*",
                                   cutoff=4)

    (Using the special case for the bulk with `soluteselection` and `cutoff`
    improves performance over the simple `update_selection` approach.)

    .. versionchanged:: 0.13.0
       *update_selection* and *quiet* keywords added

    .. deprecated:: 0.16
       The keyword argument *quiet* is deprecated in favor of *verbose*.

    """
    u = universe

    if cutoff > 0 and soluteselection is not None:
        # special fast selection for '<atomsel> not within <cutoff> of <solutesel>'
        notwithin_coordinates = notwithin_coordinates_factory(
            u,
            atomselection,
            soluteselection,
            cutoff,
            use_kdtree=use_kdtree,
            updating_selection=update_selection)

        def current_coordinates():
            return notwithin_coordinates()
    else:
        group = u.select_atoms(atomselection, updating=update_selection)

        def current_coordinates():
            return group.positions

    coord = current_coordinates()
    logger.info(
        "Selected {0:d} atoms out of {1:d} atoms ({2!s}) from {3:d} total."
        "".format(coord.shape[0], len(u.select_atoms(atomselection)),
                  atomselection, len(u.atoms)))

    # mild warning; typically this is run on RMS-fitted trajectories and
    # so the box information is rather meaningless
    box, angles = u.trajectory.ts.dimensions[:3], u.trajectory.ts.dimensions[
        3:]
    if tuple(angles) != (90., 90., 90.):
        msg = "Non-orthorhombic unit-cell --- make sure that it has been remapped properly!"
        warnings.warn(msg)
        logger.warning(msg)

    # Make the box bigger to avoid as much as possible 'outlier'. This
    # is important if the sites are defined at a high density: in this
    # case the bulk regions don't have to be close to 1 * n0 but can
    # be less. It's much more difficult to deal with outliers.  The
    # ideal solution would use images: implement 'looking across the
    # periodic boundaries' but that gets complicate when the box
    # rotates due to RMS fitting.
    smin = np.min(coord, axis=0) - padding
    smax = np.max(coord, axis=0) + padding

    BINS = fixedwidth_bins(delta, smin, smax)
    arange = np.vstack((BINS['min'], BINS['max']))
    arange = np.transpose(arange)
    bins = BINS['Nbins']

    # create empty grid with the right dimensions (and get the edges)
    grid, edges = np.histogramdd(np.zeros((1, 3)),
                                 bins=bins,
                                 range=arange,
                                 normed=False)
    grid *= 0.0
    h = grid.copy()

    pm = ProgressMeter(u.trajectory.n_frames,
                       interval=interval,
                       verbose=verbose,
                       quiet=quiet,
                       format="Histogramming %(n_atoms)6d atoms in frame "
                       "%(step)5d/%(numsteps)d  [%(percentage)5.1f%%]\r")
    start, stop, step = u.trajectory.check_slice_indices(start, stop, step)
    for ts in u.trajectory[start:stop:step]:
        coord = current_coordinates()

        pm.echo(ts.frame, n_atoms=len(coord))
        if len(coord) == 0:
            continue

        h[:], edges[:] = np.histogramdd(coord,
                                        bins=bins,
                                        range=arange,
                                        normed=False)
        grid += h  # accumulate average histogram

    n_frames = len(range(start, stop, step))
    grid /= float(n_frames)

    metadata = metadata if metadata is not None else {}
    metadata['psf'] = u.filename
    metadata['dcd'] = u.trajectory.filename
    metadata['atomselection'] = atomselection
    metadata['n_frames'] = n_frames
    metadata['totaltime'] = round(u.trajectory.n_frames * u.trajectory.dt, 3)
    metadata['dt'] = u.trajectory.dt
    metadata['time_unit'] = MDAnalysis.core.flags['time_unit']
    try:
        metadata['trajectory_skip'] = u.trajectory.skip_timestep  # frames
    except AttributeError:
        metadata['trajectory_skip'] = 1  # seems to not be used..
    try:
        metadata['trajectory_delta'] = u.trajectory.delta  # in native units
    except AttributeError:
        metadata['trajectory_delta'] = 1
    if cutoff > 0 and soluteselection is not None:
        metadata['soluteselection'] = soluteselection
        metadata['cutoff'] = cutoff  # in Angstrom

    parameters = parameters if parameters is not None else {}
    parameters['isDensity'] = False  # must override

    g = Density(grid=grid,
                edges=edges,
                units={'length': MDAnalysis.core.flags['length_unit']},
                parameters=parameters,
                metadata=metadata)
    g.make_density()
    logger.info("Density completed (initial density in Angstrom**-3)")

    return g
Ejemplo n.º 8
0
    def __init__(self, pdb, delta=1.0, atomselection='resname HOH and name O',
                 metadata=None, padding=1.0, sigma=None):
        """Construct the density from psf and pdb and the atomselection.

        Parameters
        ----------
        pdb : str
            PDB file or :class:`MDAnalysis.Universe`;
        atomselection : str
            selection string (MDAnalysis syntax) for the species to be analyzed
        delta : float
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
        metadata : dict
            dictionary of additional data to be saved with the object
        padding : float
            increase histogram dimensions by padding (on top of initial box size)
        sigma : float
            width (in Angstrom) of the gaussians that are used to build up the
            density; if ``None`` (the default) then uses B-factors from pdb


        Notes
        -----
        For assigning X-ray waters to MD densities one might have to use a sigma
        of about 0.5 A to obtain a well-defined and resolved x-ray water density
        that can be easily matched to a broader density distribution.

        Examples
        --------
        The following creates the density with the B-factors from the pdb file::

          DC = BfactorDensityCreator(pdb, delta=1.0, atomselection="name HOH",
                                     padding=2, sigma=None)
          density = DC.Density()

        See Also
        --------
        :func:`density_from_PDB` for a convenience function

        """
        u = MDAnalysis.as_Universe(pdb)
        group = u.select_atoms(atomselection)
        coord = group.positions
        logger.info("Selected {0:d} atoms ({1!s}) out of {2:d} total.".format(coord.shape[0], atomselection, len(u.atoms)))
        smin = np.min(coord, axis=0) - padding
        smax = np.max(coord, axis=0) + padding

        BINS = fixedwidth_bins(delta, smin, smax)
        arange = list(zip(BINS['min'], BINS['max']))
        bins = BINS['Nbins']

        # get edges by doing a fake run
        grid, self.edges = np.histogramdd(np.zeros((1, 3)),
                                             bins=bins, range=arange, normed=False)
        self.delta = np.diag([(e[-1] - e[0]) / (len(e) - 1) for e in self.edges])
        self.midpoints = [0.5 * (e[:-1] + e[1:]) for e in self.edges]
        self.origin = [m[0] for m in self.midpoints]
        n_frames = 1

        if sigma is None:
            # histogram individually, and smear out at the same time
            # with the appropriate B-factor
            if np.any(group.bfactors == 0.0):
                wmsg = "Some B-factors are Zero (will be skipped)."
                logger.warning(wmsg)
                warnings.warn(wmsg, category=MissingDataWarning)
            rmsf = Bfactor2RMSF(group.bfactors)
            grid *= 0.0  # reset grid
            self.g = self._smear_rmsf(coord, grid, self.edges, rmsf)
        else:
            # histogram 'delta functions'
            grid, self.edges = np.histogramdd(coord, bins=bins, range=arange, normed=False)
            logger.info("Histogrammed {0:6d} atoms from pdb.".format(len(group.atoms)))
            # just a convolution of the density with a Gaussian
            self.g = self._smear_sigma(grid, sigma)

        try:
            metadata['pdb'] = pdb
        except TypeError:
            metadata = {'pdb': pdb}
        metadata['atomselection'] = atomselection
        metadata['n_frames'] = n_frames
        metadata['sigma'] = sigma
        self.metadata = metadata

        logger.info("Histogram completed (initial density in Angstrom**-3)")
Ejemplo n.º 9
0
 def test_ValueError(self):
     with pytest.raises(ValueError):
         util.fixedwidth_bins(0.1, 5.0, 4.0)
Ejemplo n.º 10
0
 def test_usage_1(self):
     ret = util.fixedwidth_bins(0.1, 4.0, 5.0)
     assert_equal(ret['Nbins'], 10)
     assert_equal(ret['delta'], 0.1)
     assert_equal(ret['min'], 4.0)
     assert_equal(ret['max'], 5.0)
Ejemplo n.º 11
0
 def test_usage_1(self):
     ret = util.fixedwidth_bins(0.1, 4.0, 5.0)
     assert_equal(ret['Nbins'], 10)
     assert_equal(ret['delta'], 0.1)
     assert_equal(ret['min'], 4.0)
     assert_equal(ret['max'], 5.0)
Ejemplo n.º 12
0
def density_from_Universe(universe, delta=1.0, atomselection='name OH2',
                          metadata=None, padding=2.0, cutoff=0, soluteselection=None,
                          use_kdtree=True, **kwargs):
    """Create a density grid from a MDAnalysis.Universe object.

      density_from_Universe(universe, delta=1.0, atomselection='name OH2', ...) --> density

    :Arguments:
      universe
            :class:`MDAnalysis.Universe` object with a trajectory

    :Keywords:
      atomselection
            selection string (MDAnalysis syntax) for the species to be analyzed
            ["name OH2"]
      delta
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
      metadata
            dictionary of additional data to be saved with the object
      padding
            increase histogram dimensions by padding (on top of initial box size)
            in Angstroem [2.0]
      soluteselection
            MDAnalysis selection for the solute, e.g. "protein" [``None``]
      cutoff
            With *cutoff*, select '<atomsel> NOT WITHIN <cutoff> OF <soluteselection>'
            (Special routines that are faster than the standard AROUND selection) [0]
      parameters
            dict with some special parameters for :class:`Density` (see doc)
      kwargs
            metadata, parameters are modified and passed on to :class:`Density`

    :Returns: :class:`Density`

    """
    try:
        universe.select_atoms('all')
        universe.trajectory.ts
    except AttributeError:
        raise TypeError("The universe must be a proper MDAnalysis.Universe instance.")
    u = universe
    if cutoff > 0 and soluteselection is not None:
        # special fast selection for '<atomsel> not within <cutoff> of <solutesel>'
        notwithin_coordinates = notwithin_coordinates_factory(u, atomselection, soluteselection, cutoff,
                                                              use_kdtree=use_kdtree)

        def current_coordinates():
            return notwithin_coordinates()
    else:
        group = u.select_atoms(atomselection)

        def current_coordinates():
            return group.coordinates()

    coord = current_coordinates()
    logger.info("Selected %d atoms out of %d atoms (%s) from %d total." %
                (coord.shape[0], len(u.select_atoms(atomselection)), atomselection, len(u.atoms)))

    # mild warning; typically this is run on RMS-fitted trajectories and
    # so the box information is rather meaningless
    box, angles = u.trajectory.ts.dimensions[:3], u.trajectory.ts.dimensions[3:]
    if tuple(angles) != (90., 90., 90.):
        msg = "Non-orthorhombic unit-cell --- make sure that it has been remapped properly!"
        warnings.warn(msg)
        logger.warn(msg)

    # Make the box bigger to avoid as much as possible 'outlier'. This
    # is important if the sites are defined at a high density: in this
    # case the bulk regions don't have to be close to 1 * n0 but can
    # be less. It's much more difficult to deal with outliers.  The
    # ideal solution would use images: implement 'looking across the
    # periodic boundaries' but that gets complicate when the box
    # rotates due to RMS fitting.
    smin = numpy.min(coord, axis=0) - padding
    smax = numpy.max(coord, axis=0) + padding

    BINS = fixedwidth_bins(delta, smin, smax)
    arange = zip(BINS['min'], BINS['max'])
    bins = BINS['Nbins']

    # create empty grid with the right dimensions (and get the edges)
    grid, edges = numpy.histogramdd(numpy.zeros((1, 3)), bins=bins, range=arange, normed=False)
    grid *= 0.0
    h = grid.copy()

    for ts in u.trajectory:
        print("Histograming %6d atoms in frame %5d/%d  [%5.1f%%]\r" % \
              (len(coord), ts.frame, u.trajectory.n_frames, 100.0 * ts.frame / u.trajectory.n_frames),)
        coord = current_coordinates()
        if len(coord) == 0:
            continue
        h[:], edges[:] = numpy.histogramdd(coord, bins=bins, range=arange, normed=False)
        grid += h  # accumulate average histogram
    print("")
    n_frames = u.trajectory.n_frames / u.trajectory.skip
    grid /= float(n_frames)

    # pick from kwargs
    metadata = kwargs.pop('metadata', {})
    metadata['psf'] = u.filename
    metadata['dcd'] = u.trajectory.filename
    metadata['atomselection'] = atomselection
    metadata['n_frames'] = n_frames
    metadata['totaltime'] = round(u.trajectory.n_frames * u.trajectory.dt, 3)
    metadata['dt'] = u.trajectory.dt
    metadata['time_unit'] = MDAnalysis.core.flags['time_unit']
    metadata['trajectory_skip'] = u.trajectory.skip_timestep  # frames
    metadata['trajectory_delta'] = u.trajectory.delta  # in native units
    if cutoff > 0 and soluteselection is not None:
        metadata['soluteselection'] = soluteselection
        metadata['cutoff'] = cutoff  # in Angstrom

    parameters = kwargs.pop('parameters', {})
    parameters['isDensity'] = False  # must override

    # all other kwargs are discarded

    g = Density(grid=grid, edges=edges, units={'length': MDAnalysis.core.flags['length_unit']},
                parameters=parameters, metadata=metadata)
    g.make_density()
    logger.info("Density completed (initial density in Angstrom**-3)")

    return g
Ejemplo n.º 13
0
    def __init__(self,
                 pdb,
                 delta=1.0,
                 atomselection='resname HOH and name O',
                 metadata=None,
                 padding=1.0,
                 sigma=None):
        """Construct the density from psf and pdb and the atomselection.

          DC = BfactorDensityCreator(pdb, delta=<delta>, atomselection=<MDAnalysis selection>,
                                  metadata=<dict>, padding=2, sigma=None)

          density = DC.Density()

        :Arguments:

          pdb
            PDB file or :class:`MDAnalysis.Universe`; a PDB is read with the
            simpl PDB reader. If the Bio.PDB reader is required, either set
            the *permissive_pdb_reader* flag to ``False`` in
            :data:`MDAnalysis.core.flags` or supply a Universe
            that was created with the `permissive` = ``False`` keyword.
          atomselection
            selection string (MDAnalysis syntax) for the species to be analyzed
          delta
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
          metadata
            dictionary of additional data to be saved with the object
          padding
            increase histogram dimensions by padding (on top of initial box size)
          sigma
            width (in Angstrom) of the gaussians that are used to build up the
            density; if None then uses B-factors from pdb

        For assigning X-ray waters to MD densities one might have to use a sigma
        of about 0.5 A to obtain a well-defined and resolved x-ray water density
        that can be easily matched to a broader density distribution.

        """
        u = MDAnalysis.as_Universe(pdb)
        group = u.select_atoms(atomselection)
        coord = group.coordinates()
        logger.info("Selected {0:d} atoms ({1!s}) out of {2:d} total.".format(
            coord.shape[0], atomselection, len(u.atoms)))
        smin = np.min(coord, axis=0) - padding
        smax = np.max(coord, axis=0) + padding

        BINS = fixedwidth_bins(delta, smin, smax)
        arange = zip(BINS['min'], BINS['max'])
        bins = BINS['Nbins']

        # get edges by doing a fake run
        grid, self.edges = np.histogramdd(np.zeros((1, 3)),
                                          bins=bins,
                                          range=arange,
                                          normed=False)
        self.delta = np.diag(
            map(lambda e: (e[-1] - e[0]) / (len(e) - 1), self.edges))
        self.midpoints = map(lambda e: 0.5 * (e[:-1] + e[1:]), self.edges)
        self.origin = map(lambda m: m[0], self.midpoints)
        n_frames = 1

        if sigma is None:
            # histogram individually, and smear out at the same time
            # with the appropriate B-factor
            if np.any(group.bfactors == 0.0):
                wmsg = "Some B-factors are Zero (will be skipped)."
                logger.warn(wmsg)
                warnings.warn(wmsg, category=MissingDataWarning)
            rmsf = Bfactor2RMSF(group.bfactors)
            grid *= 0.0  # reset grid
            self.g = self._smear_rmsf(coord, grid, self.edges, rmsf)
        else:
            # histogram 'delta functions'
            grid, self.edges = np.histogramdd(coord,
                                              bins=bins,
                                              range=arange,
                                              normed=False)
            logger.info("Histogrammed {0:6d} atoms from pdb.".format(
                len(group.atoms)))
            # just a convolution of the density with a Gaussian
            self.g = self._smear_sigma(grid, sigma)

        try:
            metadata['pdb'] = pdb
        except TypeError:
            metadata = {'pdb': pdb}
        metadata['atomselection'] = atomselection
        metadata['n_frames'] = n_frames
        metadata['sigma'] = sigma
        self.metadata = metadata

        logger.info("Histogram completed (initial density in Angstrom**-3)")
Ejemplo n.º 14
0
def density_from_Universe(universe, delta=1.0, atomselection='name OH2',
                          start=None, stop=None, step=None,
                          metadata=None, padding=2.0, cutoff=0, soluteselection=None,
                          use_kdtree=True, update_selection=False,
                          quiet=False, interval=1,
                          **kwargs):
    """Create a density grid from a :class:`MDAnalysis.Universe` object.

    The trajectory is read, frame by frame, and the atoms selected with *atomselection* are
    histogrammed on a grid with spacing *delta*::

      density_from_Universe(universe, delta=1.0, atomselection='name OH2', ...) --> density

    .. Note:: By default, the *atomselection* is static, i.e., atoms are only
              selected once at the beginning. If you want dynamically changing
              selections (such as "name OW and around 4.0 (protein and not name
              H*)") then set ``update_selection=True``. For the special case of
              calculating a density of the "bulk" solvent away from a solute
              use the optimized selections with keywords *cutoff* and
              *soluteselection*.

    :Arguments:
      universe
            :class:`MDAnalysis.Universe` object with a trajectory

    :Keywords:
      atomselection
            selection string (MDAnalysis syntax) for the species to be analyzed
            ["name OH2"]
      delta
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
      start, stop, step
            Slice the trajectory as ``trajectory[start"stop:step]``; default
            is to read the whole trajectory.
      metadata
            dictionary of additional data to be saved with the object
      padding
            increase histogram dimensions by padding (on top of initial box size)
            in Angstroem [2.0]
      soluteselection
            MDAnalysis selection for the solute, e.g. "protein" [``None``]
      cutoff
            With *cutoff*, select "<atomsel> NOT WITHIN <cutoff> OF <soluteselection>"
            (Special routines that are faster than the standard ``AROUND`` selection)
            [0]
      update_selection
            Should the selection of atoms be updated for every step? [``False``]
            - ``True``: atom selection is updated for each frame, can be slow
            - ``False``: atoms are only selected at the beginning
      quiet
            Print status update to the screen for every *interval* frame? [``False``]
            - ``True``: no status updates when a new frame is processed
            - ``False``: status update every frame (including number of atoms
              processed, which is interesting with ``update_selection=True``)
      interval
           Show status update every *interval* frame [1]
      parameters
            dict with some special parameters for :class:`Density` (see doc)
      kwargs
            metadata, parameters are modified and passed on to :class:`Density`

    :Returns: :class:`Density`

    .. versionchanged:: 0.13.0
       *update_selection* and *quite* keywords added

    """
    try:
        universe.select_atoms('all')
        universe.trajectory.ts
    except AttributeError:
        raise TypeError("The universe must be a proper MDAnalysis.Universe instance.")
    u = universe
    if cutoff > 0 and soluteselection is not None:
        # special fast selection for '<atomsel> not within <cutoff> of <solutesel>'
        notwithin_coordinates = notwithin_coordinates_factory(u, atomselection, soluteselection, cutoff,
                                                              use_kdtree=use_kdtree)
        def current_coordinates():
            return notwithin_coordinates()
    else:
        group = u.select_atoms(atomselection)

        def current_coordinates():
            return group.coordinates()

    coord = current_coordinates()
    logger.info("Selected {0:d} atoms out of {1:d} atoms ({2!s}) from {3:d} total.".format(coord.shape[0], len(u.select_atoms(atomselection)), atomselection, len(u.atoms)))

    # mild warning; typically this is run on RMS-fitted trajectories and
    # so the box information is rather meaningless
    box, angles = u.trajectory.ts.dimensions[:3], u.trajectory.ts.dimensions[3:]
    if tuple(angles) != (90., 90., 90.):
        msg = "Non-orthorhombic unit-cell --- make sure that it has been remapped properly!"
        warnings.warn(msg)
        logger.warn(msg)

    # Make the box bigger to avoid as much as possible 'outlier'. This
    # is important if the sites are defined at a high density: in this
    # case the bulk regions don't have to be close to 1 * n0 but can
    # be less. It's much more difficult to deal with outliers.  The
    # ideal solution would use images: implement 'looking across the
    # periodic boundaries' but that gets complicate when the box
    # rotates due to RMS fitting.
    smin = np.min(coord, axis=0) - padding
    smax = np.max(coord, axis=0) + padding

    BINS = fixedwidth_bins(delta, smin, smax)
    arange = zip(BINS['min'], BINS['max'])
    bins = BINS['Nbins']

    # create empty grid with the right dimensions (and get the edges)
    grid, edges = np.histogramdd(np.zeros((1, 3)), bins=bins, range=arange, normed=False)
    grid *= 0.0
    h = grid.copy()

    pm = ProgressMeter(u.trajectory.n_frames, interval=interval, quiet=quiet,
                       format="Histogramming %(n_atoms)6d atoms in frame "
                       "%(step)5d/%(numsteps)d  [%(percentage)5.1f%%]\r")
    start, stop, step = u.trajectory.check_slice_indices(start, stop, step)                    
    for ts in u.trajectory[start:stop:step]:
        if update_selection:
           group = u.select_atoms(atomselection)
           coord=group.positions
        else:
           coord = current_coordinates()

        pm.echo(ts.frame, n_atoms=len(coord))
        if len(coord) == 0:
            continue

        h[:], edges[:] = np.histogramdd(coord, bins=bins, range=arange, normed=False)
        grid += h  # accumulate average histogram
   
    
    n_frames = len(range(start, stop, step))
    grid /= float(n_frames)

    # pick from kwargs
    metadata = kwargs.pop('metadata', {})
    metadata['psf'] = u.filename
    metadata['dcd'] = u.trajectory.filename
    metadata['atomselection'] = atomselection
    metadata['n_frames'] = n_frames
    metadata['totaltime'] = round(u.trajectory.n_frames * u.trajectory.dt, 3)
    metadata['dt'] = u.trajectory.dt
    metadata['time_unit'] = MDAnalysis.core.flags['time_unit']
    try:
        metadata['trajectory_skip'] = u.trajectory.skip_timestep  # frames
    except AttributeError:
        metadata['trajectory_skip'] = 1  # seems to not be used..
    try:
        metadata['trajectory_delta'] = u.trajectory.delta  # in native units
    except AttributeError:
        metadata['trajectory_delta'] = 1
    if cutoff > 0 and soluteselection is not None:
        metadata['soluteselection'] = soluteselection
        metadata['cutoff'] = cutoff  # in Angstrom

    parameters = kwargs.pop('parameters', {})
    parameters['isDensity'] = False  # must override

    # all other kwargs are discarded

    g = Density(grid=grid, edges=edges, units={'length': MDAnalysis.core.flags['length_unit']},
                parameters=parameters, metadata=metadata)
    g.make_density()
    logger.info("Density completed (initial density in Angstrom**-3)")

    return g
Ejemplo n.º 15
0
    def __init__(self,
                 pdb,
                 delta=1.0,
                 atomselection='resname HOH and name O',
                 metadata=None,
                 padding=1.0,
                 sigma=None):
        """Construct the density from psf and pdb and the atomselection.

        Parameters
        ----------
        pdb : str
            PDB file or :class:`MDAnalysis.Universe`;
        atomselection : str
            selection string (MDAnalysis syntax) for the species to be analyzed
        delta : float
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
        metadata : dict
            dictionary of additional data to be saved with the object
        padding : float
            increase histogram dimensions by padding (on top of initial box size)
        sigma : float
            width (in Angstrom) of the gaussians that are used to build up the
            density; if ``None`` (the default) then uses B-factors from pdb


        Notes
        -----
        For assigning X-ray waters to MD densities one might have to use a sigma
        of about 0.5 A to obtain a well-defined and resolved x-ray water density
        that can be easily matched to a broader density distribution.

        Examples
        --------
        The following creates the density with the B-factors from the pdb file::

          DC = BfactorDensityCreator(pdb, delta=1.0, atomselection="name HOH",
                                     padding=2, sigma=None)
          density = DC.Density()

        See Also
        --------
        :func:`density_from_PDB` for a convenience function

        """
        u = MDAnalysis.as_Universe(pdb)
        group = u.select_atoms(atomselection)
        coord = group.positions
        logger.info("Selected {0:d} atoms ({1!s}) out of {2:d} total.".format(
            coord.shape[0], atomselection, len(u.atoms)))
        smin = np.min(coord, axis=0) - padding
        smax = np.max(coord, axis=0) + padding

        BINS = fixedwidth_bins(delta, smin, smax)
        arange = list(zip(BINS['min'], BINS['max']))
        bins = BINS['Nbins']

        # get edges by doing a fake run
        grid, self.edges = np.histogramdd(np.zeros((1, 3)),
                                          bins=bins,
                                          range=arange,
                                          normed=False)
        self.delta = np.diag([(e[-1] - e[0]) / (len(e) - 1)
                              for e in self.edges])
        self.midpoints = [0.5 * (e[:-1] + e[1:]) for e in self.edges]
        self.origin = [m[0] for m in self.midpoints]
        n_frames = 1

        if sigma is None:
            # histogram individually, and smear out at the same time
            # with the appropriate B-factor
            if np.any(group.bfactors == 0.0):
                wmsg = "Some B-factors are Zero (will be skipped)."
                logger.warning(wmsg)
                warnings.warn(wmsg, category=MissingDataWarning)
            rmsf = Bfactor2RMSF(group.bfactors)
            grid *= 0.0  # reset grid
            self.g = self._smear_rmsf(coord, grid, self.edges, rmsf)
        else:
            # histogram 'delta functions'
            grid, self.edges = np.histogramdd(coord,
                                              bins=bins,
                                              range=arange,
                                              normed=False)
            logger.info("Histogrammed {0:6d} atoms from pdb.".format(
                len(group.atoms)))
            # just a convolution of the density with a Gaussian
            self.g = self._smear_sigma(grid, sigma)

        try:
            metadata['pdb'] = pdb
        except TypeError:
            metadata = {'pdb': pdb}
        metadata['atomselection'] = atomselection
        metadata['n_frames'] = n_frames
        metadata['sigma'] = sigma
        self.metadata = metadata

        logger.info("Histogram completed (initial density in Angstrom**-3)")
Ejemplo n.º 16
0
    def __init__(self, pdb, delta=1.0, atomselection='resname HOH and name O',
                 metadata=None, padding=1.0, sigma=None):
        """Construct the density from psf and pdb and the atomselection.

          DC = BfactorDensityCreator(pdb, delta=<delta>, atomselection=<MDAnalysis selection>,
                                  metadata=<dict>, padding=2, sigma=None)

          density = DC.Density()

        :Arguments:

          pdb
            PDB file or :class:`MDAnalysis.Universe`; a PDB is read with the
            simpl PDB reader. If the Bio.PDB reader is required, either set
            the *permissive_pdb_reader* flag to ``False`` in
            :data:`MDAnalysis.core.flags` or supply a Universe
            that was created with the `permissive` = ``False`` keyword.
          atomselection
            selection string (MDAnalysis syntax) for the species to be analyzed
          delta
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
          metadata
            dictionary of additional data to be saved with the object
          padding
            increase histogram dimensions by padding (on top of initial box size)
          sigma
            width (in Angstrom) of the gaussians that are used to build up the
            density; if None then uses B-factors from pdb

        For assigning X-ray waters to MD densities one might have to use a sigma
        of about 0.5 A to obtain a well-defined and resolved x-ray water density
        that can be easily matched to a broader density distribution.

        """
        u = MDAnalysis.as_Universe(pdb)
        group = u.select_atoms(atomselection)
        coord = group.coordinates()
        logger.info("Selected {0:d} atoms ({1!s}) out of {2:d} total.".format(coord.shape[0], atomselection, len(u.atoms)))
        smin = np.min(coord, axis=0) - padding
        smax = np.max(coord, axis=0) + padding

        BINS = fixedwidth_bins(delta, smin, smax)
        arange = zip(BINS['min'], BINS['max'])
        bins = BINS['Nbins']

        # get edges by doing a fake run
        grid, self.edges = np.histogramdd(np.zeros((1, 3)),
                                             bins=bins, range=arange, normed=False)
        self.delta = np.diag(map(lambda e: (e[-1] - e[0]) / (len(e) - 1), self.edges))
        self.midpoints = map(lambda e: 0.5 * (e[:-1] + e[1:]), self.edges)
        self.origin = map(lambda m: m[0], self.midpoints)
        n_frames = 1

        if sigma is None:
            # histogram individually, and smear out at the same time
            # with the appropriate B-factor
            if np.any(group.bfactors == 0.0):
                wmsg = "Some B-factors are Zero (will be skipped)."
                logger.warn(wmsg)
                warnings.warn(wmsg, category=MissingDataWarning)
            rmsf = Bfactor2RMSF(group.bfactors)
            grid *= 0.0  # reset grid
            self.g = self._smear_rmsf(coord, grid, self.edges, rmsf)
        else:
            # histogram 'delta functions'
            grid, self.edges = np.histogramdd(coord, bins=bins, range=arange, normed=False)
            logger.info("Histogrammed {0:6d} atoms from pdb.".format(len(group.atoms)))
            # just a convolution of the density with a Gaussian
            self.g = self._smear_sigma(grid, sigma)

        try:
            metadata['pdb'] = pdb
        except TypeError:
            metadata = {'pdb': pdb}
        metadata['atomselection'] = atomselection
        metadata['n_frames'] = n_frames
        metadata['sigma'] = sigma
        self.metadata = metadata

        logger.info("Histogram completed (initial density in Angstrom**-3)")
Ejemplo n.º 17
0
 def test_keys(self):
     ret = util.fixedwidth_bins(0.5, 1.0, 2.0)
     for k in ['Nbins', 'delta', 'min', 'max']:
         assert k in ret
Ejemplo n.º 18
0
def density_from_Universe(universe, delta=1.0, atomselection='name OH2',
                          start=None, stop=None, step=None,
                          metadata=None, padding=2.0, cutoff=0, soluteselection=None,
                          use_kdtree=True, update_selection=False,
                          verbose=False, interval=1, quiet=None,
                          parameters=None,
                          gridcenter=None, xdim=None, ydim=None, zdim=None):
    """Create a density grid from a :class:`MDAnalysis.Universe` object.

    The trajectory is read, frame by frame, and the atoms selected with `atomselection` are
    histogrammed on a grid with spacing `delta`.

    Parameters
    ----------
    universe : MDAnalysis.Universe
            :class:`MDAnalysis.Universe` object with a trajectory
    atomselection : str (optional)
            selection string (MDAnalysis syntax) for the species to be analyzed
            ["name OH2"]
    delta : float (optional)
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
    start : int (optional)
    stop : int (optional)
    step : int (optional)
            Slice the trajectory as ``trajectory[start:stop:step]``; default
            is to read the whole trajectory.
    metadata : dict. optional
            `dict` of additional data to be saved with the object; the meta data
            are passed through as they are.
    padding : float (optional)
            increase histogram dimensions by padding (on top of initial box size)
            in Angstroem. Padding is ignored when setting a user defined grid. [2.0]
    soluteselection : str (optional)
            MDAnalysis selection for the solute, e.g. "protein" [``None``]
    cutoff : float (optional)
            With `cutoff`, select "<atomsel> NOT WITHIN <cutoff> OF <soluteselection>"
            (Special routines that are faster than the standard ``AROUND`` selection);
            any value that evaluates to ``False`` (such as the default 0) disables this
            special selection.
    update_selection : bool (optional)
            Should the selection of atoms be updated for every step? [``False``]

            - ``True``: atom selection is updated for each frame, can be slow
            - ``False``: atoms are only selected at the beginning
    verbose : bool (optional)
            Print status update to the screen for every *interval* frame? [``True``]

            - ``False``: no status updates when a new frame is processed
            - ``True``: status update every frame (including number of atoms
              processed, which is interesting with ``update_selection=True``)
    interval : int (optional)
           Show status update every `interval` frame [1]
    parameters : dict (optional)
            `dict` with some special parameters for :class:`Density` (see docs)
    gridcenter : numpy ndarray, float32 (optional)
            3 element numpy array detailing the x, y and z coordinates of the
            center of a user defined grid box in Angstroem [``None``]
    xdim : float (optional)
            User defined x dimension box edge in ångström; ignored if
            gridcenter is ``None``
    ydim : float (optional)
            User defined y dimension box edge in ångström; ignored if
            gridcenter is ``None``
    zdim : float (optional)
            User defined z dimension box edge in ångström; ignored if
            gridcenter is ``None``

    Returns
    -------
    :class:`Density`
            A :class:`Density` instance with the histogrammed data together
            with associated metadata.


    Notes
    -----

    By default, the `atomselection` is static, i.e., atoms are only selected
    once at the beginning. If you want *dynamically changing selections* (such
    as "name OW and around 4.0 (protein and not name H*)", i.e., the water
    oxygen atoms that are within 4 Å of the protein heavy atoms) then set
    ``update_selection=True``. For the special case of calculating a density of
    the "bulk" solvent away from a solute use the optimized selections with
    keywords *cutoff* and *soluteselection* (see Examples below).

    Examples
    --------
    Basic use for creating a water density (just using the water oxygen atoms "OW")::

      density = density_from_Universe(universe, delta=1.0, atomselection='name OW')

    If you are only interested in water within a certain region, e.g., within a
    vicinity around a binding site, you can use a selection that updates every
    step by setting the `update_selection` keyword argument::

      site_density = density_from_Universe(universe, delta=1.0,
                                           atomselection='name OW and around 5 (resid 156 157 305)',
                                           update_selection=True)

    A special case for an updating selection is to create the "bulk density",
    i.e., the water outside the immediate solvation shell of a protein: Select
    all water oxygen atoms that are *farther away* than a given cut-off (say, 4
    Å) from the solute (here, heavy atoms of the protein)::

      bulk = density_from_Universe(universe, delta=1.0, atomselection='name OW',
                                   solute="protein and not name H*",
                                   cutoff=4)

    (Using the special case for the bulk with `soluteselection` and `cutoff`
    improves performance over the simple `update_selection` approach.)

    If you are interested in explicitly setting a grid box of a given edge size
    and origin, you can use the gridcenter and x/y/zdim arguments. For example
    to plot the density of waters within 5 Å of a ligand (in this case the
    ligand has been assigned the residue name "LIG") in a cubic grid with 20 Å
    edges which is centered on the centre of mass (COM) of the ligand::

      # Create a selection based on the ligand
      ligand_selection = universe.select_atoms("resname LIG")

      # Extract the COM of the ligand
      ligand_COM = ligand_selection.center_of_mass()

      # Generate a density of waters on a cubic grid centered on the ligand COM
      # In this case, we update the atom selection as shown above.
      water_density = density_from_Universe(universe, delta=1.0,
                                            atomselection='name OW around 5 resname LIG',
                                            update_selection=True,
                                            gridcenter=ligand_COM,
                                            xdim=20.0, ydim=20.0, zdim=20.0)

      (It should be noted that the `padding` keyword is not used when a user
      defined grid is assigned).

    .. versionchanged:: 0.19.0
       *gridcenter*, *xdim*, *ydim* and *zdim* keywords added to allow for user
       defined boxes
    .. versionchanged:: 0.13.0
       *update_selection* and *quiet* keywords added

    .. deprecated:: 0.16
       The keyword argument *quiet* is deprecated in favor of *verbose*.

    """
    u = universe

    if cutoff > 0 and soluteselection is not None:
        # special fast selection for '<atomsel> not within <cutoff> of <solutesel>'
        notwithin_coordinates = notwithin_coordinates_factory(
            u, atomselection, soluteselection, cutoff,
            use_kdtree=use_kdtree, updating_selection=update_selection)
        def current_coordinates():
            return notwithin_coordinates()
    else:
        group = u.select_atoms(atomselection, updating=update_selection)

        def current_coordinates():
            return group.positions

    coord = current_coordinates()
    logger.info(
        "Selected {0:d} atoms out of {1:d} atoms ({2!s}) from {3:d} total."
        "".format(coord.shape[0], len(u.select_atoms(atomselection)),
                  atomselection, len(u.atoms))
    )

    # mild warning; typically this is run on RMS-fitted trajectories and
    # so the box information is rather meaningless
    box, angles = u.trajectory.ts.dimensions[:3], u.trajectory.ts.dimensions[3:]
    if tuple(angles) != (90., 90., 90.):
        msg = "Non-orthorhombic unit-cell --- make sure that it has been remapped properly!"
        warnings.warn(msg)
        logger.warning(msg)

    if gridcenter is not None:
        # Generate a copy of smin/smax from coords to later check if the
        # defined box might be too small for the selection
        smin = np.min(coord, axis=0)
        smax = np.max(coord, axis=0)
        # Overwrite smin/smax with user defined values
        smin, smax = _set_user_grid(gridcenter, xdim, ydim, zdim, smin, smax)
    else:
        # Make the box bigger to avoid as much as possible 'outlier'. This
        # is important if the sites are defined at a high density: in this
        # case the bulk regions don't have to be close to 1 * n0 but can
        # be less. It's much more difficult to deal with outliers.  The
        # ideal solution would use images: implement 'looking across the
        # periodic boundaries' but that gets complicate when the box
        # rotates due to RMS fitting.
        smin = np.min(coord, axis=0) - padding
        smax = np.max(coord, axis=0) + padding

    BINS = fixedwidth_bins(delta, smin, smax)
    arange = np.vstack((BINS['min'], BINS['max']))
    arange = np.transpose(arange)
    bins = BINS['Nbins']

    # create empty grid with the right dimensions (and get the edges)
    grid, edges = np.histogramdd(np.zeros((1, 3)), bins=bins, range=arange, normed=False)
    grid *= 0.0
    h = grid.copy()

    pm = ProgressMeter(u.trajectory.n_frames, interval=interval,
                       verbose=verbose,
                       format="Histogramming %(n_atoms)6d atoms in frame "
                       "%(step)5d/%(numsteps)d  [%(percentage)5.1f%%]\r")
    start, stop, step = u.trajectory.check_slice_indices(start, stop, step)
    for ts in u.trajectory[start:stop:step]:
        coord = current_coordinates()

        pm.echo(ts.frame, n_atoms=len(coord))
        if len(coord) == 0:
            continue

        h[:], edges[:] = np.histogramdd(coord, bins=bins, range=arange, normed=False)
        grid += h  # accumulate average histogram

    n_frames = len(range(start, stop, step))
    grid /= float(n_frames)

    metadata = metadata if metadata is not None else {}
    metadata['psf'] = u.filename
    metadata['dcd'] = u.trajectory.filename
    metadata['atomselection'] = atomselection
    metadata['n_frames'] = n_frames
    metadata['totaltime'] = round(u.trajectory.n_frames * u.trajectory.dt, 3)
    metadata['dt'] = u.trajectory.dt
    metadata['time_unit'] = MDAnalysis.core.flags['time_unit']
    try:
        metadata['trajectory_skip'] = u.trajectory.skip_timestep  # frames
    except AttributeError:
        metadata['trajectory_skip'] = 1  # seems to not be used..
    try:
        metadata['trajectory_delta'] = u.trajectory.delta  # in native units
    except AttributeError:
        metadata['trajectory_delta'] = 1
    if cutoff > 0 and soluteselection is not None:
        metadata['soluteselection'] = soluteselection
        metadata['cutoff'] = cutoff  # in Angstrom

    parameters = parameters if parameters is not None else {}
    parameters['isDensity'] = False  # must override


    g = Density(grid=grid, edges=edges, units={'length': MDAnalysis.core.flags['length_unit']},
                parameters=parameters, metadata=metadata)
    g.make_density()
    logger.info("Density completed (initial density in Angstrom**-3)")

    return g
Ejemplo n.º 19
0
def density_from_Universe(universe, delta=1.0, atomselection='name OH2',
                          metadata=None, padding=2.0, cutoff=0, soluteselection=None,
                          use_kdtree=True, **kwargs):
    """Create a density grid from a MDAnalysis.Universe object.

      density_from_Universe(universe, delta=1.0, atomselection='name OH2', ...) --> density

    :Arguments:
      universe
            :class:`MDAnalysis.Universe` object with a trajectory

    :Keywords:
      atomselection
            selection string (MDAnalysis syntax) for the species to be analyzed
            ["name OH2"]
      delta
            bin size for the density grid in Angstroem (same in x,y,z) [1.0]
      metadata
            dictionary of additional data to be saved with the object
      padding
            increase histogram dimensions by padding (on top of initial box size)
            in Angstroem [2.0]
      soluteselection
            MDAnalysis selection for the solute, e.g. "protein" [``None``]
      cutoff
            With *cutoff*, select '<atomsel> NOT WITHIN <cutoff> OF <soluteselection>'
            (Special routines that are faster than the standard AROUND selection) [0]
      parameters
            dict with some special parameters for :class:`Density` (see doc)
      kwargs
            metadata, parameters are modified and passed on to :class:`Density`

    :Returns: :class:`Density`

    """
    try:
        universe.select_atoms('all')
        universe.trajectory.ts
    except AttributeError:
        raise TypeError("The universe must be a proper MDAnalysis.Universe instance.")
    u = universe
    if cutoff > 0 and soluteselection is not None:
        # special fast selection for '<atomsel> not within <cutoff> of <solutesel>'
        notwithin_coordinates = notwithin_coordinates_factory(u, atomselection, soluteselection, cutoff,
                                                              use_kdtree=use_kdtree)

        def current_coordinates():
            return notwithin_coordinates()
    else:
        group = u.select_atoms(atomselection)

        def current_coordinates():
            return group.coordinates()

    coord = current_coordinates()
    logger.info("Selected %d atoms out of %d atoms (%s) from %d total." %
                (coord.shape[0], len(u.select_atoms(atomselection)), atomselection, len(u.atoms)))

    # mild warning; typically this is run on RMS-fitted trajectories and
    # so the box information is rather meaningless
    box, angles = u.trajectory.ts.dimensions[:3], u.trajectory.ts.dimensions[3:]
    if tuple(angles) != (90., 90., 90.):
        msg = "Non-orthorhombic unit-cell --- make sure that it has been remapped properly!"
        warnings.warn(msg)
        logger.warn(msg)

    # Make the box bigger to avoid as much as possible 'outlier'. This
    # is important if the sites are defined at a high density: in this
    # case the bulk regions don't have to be close to 1 * n0 but can
    # be less. It's much more difficult to deal with outliers.  The
    # ideal solution would use images: implement 'looking across the
    # periodic boundaries' but that gets complicate when the box
    # rotates due to RMS fitting.
    smin = np.min(coord, axis=0) - padding
    smax = np.max(coord, axis=0) + padding

    BINS = fixedwidth_bins(delta, smin, smax)
    arange = zip(BINS['min'], BINS['max'])
    bins = BINS['Nbins']

    # create empty grid with the right dimensions (and get the edges)
    grid, edges = np.histogramdd(np.zeros((1, 3)), bins=bins, range=arange, normed=False)
    grid *= 0.0
    h = grid.copy()

    for ts in u.trajectory:
        print("Histograming %6d atoms in frame %5d/%d  [%5.1f%%]\r" % \
              (len(coord), ts.frame, u.trajectory.n_frames, 100.0 * ts.frame / u.trajectory.n_frames),)
        coord = current_coordinates()
        if len(coord) == 0:
            continue
        h[:], edges[:] = np.histogramdd(coord, bins=bins, range=arange, normed=False)
        grid += h  # accumulate average histogram
    print("")
    n_frames = u.trajectory.n_frames / u.trajectory.skip
    grid /= float(n_frames)

    # pick from kwargs
    metadata = kwargs.pop('metadata', {})
    metadata['psf'] = u.filename
    metadata['dcd'] = u.trajectory.filename
    metadata['atomselection'] = atomselection
    metadata['n_frames'] = n_frames
    metadata['totaltime'] = round(u.trajectory.n_frames * u.trajectory.dt, 3)
    metadata['dt'] = u.trajectory.dt
    metadata['time_unit'] = MDAnalysis.core.flags['time_unit']
    metadata['trajectory_skip'] = u.trajectory.skip_timestep  # frames
    metadata['trajectory_delta'] = u.trajectory.delta  # in native units
    if cutoff > 0 and soluteselection is not None:
        metadata['soluteselection'] = soluteselection
        metadata['cutoff'] = cutoff  # in Angstrom

    parameters = kwargs.pop('parameters', {})
    parameters['isDensity'] = False  # must override

    # all other kwargs are discarded

    g = Density(grid=grid, edges=edges, units={'length': MDAnalysis.core.flags['length_unit']},
                parameters=parameters, metadata=metadata)
    g.make_density()
    logger.info("Density completed (initial density in Angstrom**-3)")

    return g