示例#1
0
    def __init__(self, filename, **kwargs):
        self.filename = util.filename(filename, ext=native_str("stream"))
        self._version = kwargs.get("charmm_version", 41)

        width = 4 if self._version < 36 else 8
        if self._version >= 36:
            self.fmt = ("""
                IC EDIT
                DIST %-{width}s %{width}d %-{width}s %-{width}s %{width}d %-{width}s%{width}.1f
                END
                """.format(width=width))
        else:
            self.fmt = ("""
                IC EDIT
                DIST BYNUM %{width}d BYNUM %{width}d %{width}.1f
                END
                """.format(width=width))

        date = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
        user = environ["USER"]
        self._title = kwargs.get(
            "title", (
                "* Created by fluctmatch on {date}".format(date=date),
                "* User: {user}".format(user=user),
            ))
        if not util.iterable(self._title):
            self._title = util.asiterable(self._title)
示例#2
0
    def __init__(self, filename, **kwargs):
        self.filename = util.filename(filename, ext="prm")
        self._version = kwargs.get("charmm_version", 41)
        self._nonbonded = kwargs.get("nonbonded", False)

        date = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
        user = environ["USER"]
        self._title = kwargs.get("title", (
            "* Created by fluctmatch on {date}".format(date=date),
            "* User: {user}".format(user=user),
        ))
        if not util.iterable(self._title):
            self._title = util.asiterable(self._title)
示例#3
0
    def _prepare(self):
        self._n_atoms = self.mobile_atoms.n_atoms

        if not iterable(self.weights) and self.weights == 'mass':
            self.weights = self.ref_atoms.masses
        if self.weights is not None:
            self.weights = np.asarray(self.weights,
                                      dtype=np.float64) / np.mean(self.weights)

        current_frame = self.reference.universe.trajectory.ts.frame

        try:
            # Move to the ref_frame
            # (coordinates MUST be stored in case the ref traj is advanced
            # elsewhere or if ref == mobile universe)
            self.reference.universe.trajectory[self.ref_frame]
            self._ref_com = self.ref_atoms.center(self.weights)
            # makes a copy
            self._ref_coordinates = self.ref_atoms.positions - self._ref_com
            if self._groupselections_atoms:
                self._groupselections_ref_coords64 = [
                    (self.reference.select_atoms(
                        *s['reference']).positions.astype(np.float64))
                    for s in self.groupselections
                ]
        finally:
            # Move back to the original frame
            self.reference.universe.trajectory[current_frame]

        self._ref_coordinates64 = self._ref_coordinates.astype(np.float64)

        if self._groupselections_atoms:
            # Only carry out a rotation if we want to calculate secondary
            # RMSDs.
            # R: rotation matrix that aligns r-r_com, x~-x~com
            #    (x~: selected coordinates, x: all coordinates)
            # Final transformed traj coordinates: x' = (x-x~_com)*R + ref_com
            self._rot = np.zeros(9, dtype=np.float64)  # allocate space
            self._R = self._rot.reshape(3, 3)
        else:
            self._rot = None

        self.rmsd = np.zeros(
            (self.n_frames, 3 + len(self._groupselections_atoms)))

        self._pm.format = ("RMSD {rmsd:5.2f} A at frame "
                           "{step:5d}/{numsteps}  [{percentage:5.1f}%]")
        self._mobile_coordinates64 = self.mobile_atoms.positions.copy().astype(
            np.float64)
示例#4
0
    def __init__(self, filename, **kwargs):
        self.filename = util.filename(filename, ext="ic")
        self._intcor = None
        self._extended = kwargs.get("extended", True)
        self._resid = kwargs.get("resid", True)
        self.key = "EXTENDED" if self._extended else "STANDARD"
        self.key += "_RESID" if self._resid else ""

        date = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
        user = environ["USER"]
        self._title = kwargs.get(
            "title", (
                "* Created by fluctmatch on {date}".format(date=date),
                "* User: {user}".format(user=user),
            ))
        if not util.iterable(self._title):
            self._title = util.asiterable(self._title)
示例#5
0
    def _prepare(self):
        self._n_atoms = self.mobile_atoms.n_atoms

        if not iterable(self.weights) and self.weights == 'mass':
            self.weights = self.ref_atoms.masses
        if self.weights is not None:
            self.weights = np.asarray(self.weights, dtype=np.float64) / np.mean(self.weights)

        current_frame = self.reference.universe.trajectory.ts.frame

        try:
            # Move to the ref_frame
            # (coordinates MUST be stored in case the ref traj is advanced
            # elsewhere or if ref == mobile universe)
            self.reference.universe.trajectory[self.ref_frame]
            self._ref_com = self.ref_atoms.center(self.weights)
            # makes a copy
            self._ref_coordinates = self.ref_atoms.positions - self._ref_com
            if self._groupselections_atoms:
                self._groupselections_ref_coords64 = [(self.reference.
                    select_atoms(*s['reference']).
                    positions.astype(np.float64)) for s in
                    self.groupselections]
        finally:
            # Move back to the original frame
            self.reference.universe.trajectory[current_frame]

        self._ref_coordinates64 = self._ref_coordinates.astype(np.float64)

        if self._groupselections_atoms:
            # Only carry out a rotation if we want to calculate secondary
            # RMSDs.
            # R: rotation matrix that aligns r-r_com, x~-x~com
            #    (x~: selected coordinates, x: all coordinates)
            # Final transformed traj coordinates: x' = (x-x~_com)*R + ref_com
            self._rot = np.zeros(9, dtype=np.float64)  # allocate space
            self._R = self._rot.reshape(3, 3)
        else:
            self._rot = None

        self.rmsd = np.zeros((self.n_frames,
                              3 + len(self._groupselections_atoms)))

        self._pm.format = ("RMSD {rmsd:5.2f} A at frame "
                           "{step:5d}/{numsteps}  [{percentage:5.1f}%]\r")
        self._mobile_coordinates64 = self.mobile_atoms.positions.copy().astype(np.float64)
示例#6
0
def test_iterable(iterable, value):
    assert util.iterable(iterable) == value
示例#7
0
    def _prepare(self):
        self._n_atoms = self.mobile_atoms.n_atoms
        if not self.weights_groupselections:
            if not iterable(
                    self.weights):  # apply 'mass' or 'None' to groupselections
                self.weights_groupselections = [self.weights] * len(
                    self.groupselections)
            else:
                self.weights_groupselections = [None] * len(
                    self.groupselections)

        for igroup, (weights, atoms) in enumerate(
                zip(self.weights_groupselections,
                    self._groupselections_atoms)):
            if str(weights) == 'mass':
                self.weights_groupselections[igroup] = atoms['mobile'].masses
            if weights is not None:
                self.weights_groupselections[igroup] = np.asarray(self.weights_groupselections[igroup],
                                                                  dtype=np.float64) /  \
                                             np.mean(self.weights_groupselections[igroup])
        # add the array of weights to weights_select
        self.weights_select = get_weights(self.mobile_atoms, self.weights)
        self.weights_ref = get_weights(self.ref_atoms, self.weights)
        if self.weights_select is not None:
            self.weights_select = np.asarray(self.weights_select, dtype=np.float64) /  \
                                  np.mean(self.weights_select)
            self.weights_ref = np.asarray(self.weights_ref, dtype=np.float64) / \
                               np.mean(self.weights_ref)

        current_frame = self.reference.universe.trajectory.ts.frame

        try:
            # Move to the ref_frame
            # (coordinates MUST be stored in case the ref traj is advanced
            # elsewhere or if ref == mobile universe)
            self.reference.universe.trajectory[self.ref_frame]
            self._ref_com = self.ref_atoms.center(self.weights_ref)
            # makes a copy
            self._ref_coordinates = self.ref_atoms.positions - self._ref_com
            if self._groupselections_atoms:
                self._groupselections_ref_coords64 = [
                    (self.reference.select_atoms(
                        *s['reference']).positions.astype(np.float64))
                    for s in self.groupselections
                ]
        finally:
            # Move back to the original frame
            self.reference.universe.trajectory[current_frame]

        self._ref_coordinates64 = self._ref_coordinates.astype(np.float64)

        if self._groupselections_atoms:
            # Only carry out a rotation if we want to calculate secondary
            # RMSDs.
            # R: rotation matrix that aligns r-r_com, x~-x~com
            #    (x~: selected coordinates, x: all coordinates)
            # Final transformed traj coordinates: x' = (x-x~_com)*R + ref_com
            self._rot = np.zeros(9, dtype=np.float64)  # allocate space
            self._R = self._rot.reshape(3, 3)
        else:
            self._rot = None

        self.rmsd = np.zeros(
            (self.n_frames, 3 + len(self._groupselections_atoms)))

        self._mobile_coordinates64 = self.mobile_atoms.positions.copy().astype(
            np.float64)
示例#8
0
 def test_lists(self):
     assert_equal(util.iterable([1, 2, 3]), True)
     assert_equal(util.iterable([]), True)
示例#9
0
 def test_strings(self):
     """Test that iterable() works on any string (Fixed bug)"""
     assert_equal(util.iterable("byte string"), False)
     assert_equal(util.iterable(u"unicode string"), False)
示例#10
0
 def test_scalars(self):
     assert_equal(util.iterable(123), False)
示例#11
0
 def test_arrays(self):
     assert_equal(util.iterable(numpy.array([1, 2, 3])), True)
示例#12
0
 def test_iterator(self):
     assert_equal(util.iterable(range(3)), True)
示例#13
0
    def __init__(self, atomgroup, reference=None, select='all',
                 groupselections=None, filename="rmsd.dat",
                 weights=None, tol_mass=0.1, ref_frame=0, **kwargs):
        # DEPRECATION: remove filename kwarg in 1.0
        r"""Parameters
        ----------
        atomgroup : AtomGroup or Universe
            Group of atoms for which the RMSD is calculated. If a trajectory is
            associated with the atoms then the computation iterates over the
            trajectory.
        reference : AtomGroup or Universe (optional)
            Group of reference atoms; if ``None`` then the current frame of
            `atomgroup` is used.
        select : str or dict or tuple (optional)
            The selection to operate on; can be one of:

            1. any valid selection string for
               :meth:`~MDAnalysis.core.groups.AtomGroup.select_atoms` that
               produces identical selections in `atomgroup` and `reference`; or

            2. a dictionary ``{'mobile': sel1, 'reference': sel2}`` where *sel1*
               and *sel2* are valid selection strings that are applied to
               `atomgroup` and `reference` respectively (the
               :func:`MDAnalysis.analysis.align.fasta2select` function returns such
               a dictionary based on a ClustalW_ or STAMP_ sequence alignment); or

            3. a tuple ``(sel1, sel2)``

            When using 2. or 3. with *sel1* and *sel2* then these selection strings
            are applied to `atomgroup` and `reference` respectively and should
            generate *groups of equivalent atoms*.  *sel1* and *sel2* can each also
            be a *list of selection strings* to generate a
            :class:`~MDAnalysis.core.groups.AtomGroup` with defined atom order as
            described under :ref:`ordered-selections-label`).

        groupselections : list (optional)
            A list of selections as described for `select`, with the difference
            that these selections are *always applied to the full universes*,
            i.e., ``atomgroup.universe.select_atoms(sel1)`` and
            ``reference.universe.select_atoms(sel2)``. Each selection describes
            additional RMSDs to be computed *after the structures have been
            superimposed* according to `select`. No additional fitting is
            performed.The output contains one additional column for each
            selection.

            .. Note:: Experimental feature. Only limited error checking
                      implemented.
        filename : str (optional)
            write RMSD into file with :meth:`RMSD.save`

            .. deprecated:; 0.19.0
               `filename` will be removed together with :meth:`save` in 1.0.

        weights : {"mass", ``None``} or array_like (optional)
             choose weights. With ``"mass"`` uses masses as weights; with ``None``
             weigh each atom equally. If a float array of the same length as
             `atomgroup` is provided, use each element of the `array_like` as a
             weight for the corresponding atom in `atomgroup`.
        tol_mass : float (optional)
             Reject match if the atomic masses for matched atoms differ by more
             than `tol_mass`.
        ref_frame : int (optional)
             frame index to select frame from `reference`
        verbose : bool (optional)
             Show detailed progress of the calculation if set to ``True``; the
             default is ``False``.

        Raises
        ------
        SelectionError
             If the selections from `atomgroup` and `reference` do not match.
        TypeError
             If `weights` is not of the appropriate type; see also
             :func:`MDAnalysis.lib.util.get_weights`
        ValueError
             If `weights` are not compatible with `atomgroup` (not the same
             length) or if it is not a 1D array (see
             :func:`MDAnalysis.lib.util.get_weights`).

             A :exc:`ValueError` is also raised if `weights` are not compatible
             with `groupselections`: only equal weights (``weights=None``) or
             mass-weighted (``weights="mass"``) are supported for additional
             `groupselections`.

        Notes
        -----
        The root mean square deviation :math:`\rho(t)` of a group of :math:`N`
        atoms relative to a reference structure as a function of time is
        calculated as

        .. math::

           \rho(t) = \sqrt{\frac{1}{N} \sum_{i=1}^N w_i \left(\mathbf{x}_i(t)
                                    - \mathbf{x}_i^{\text{ref}}\right)^2}

        The weights :math:`w_i` are calculated from the input weights `weights`
        :math:`w'_i` as relative to the mean of the input weights:

        .. math::

           w_i = \frac{w'_i}{\langle w' \rangle}

        The selected coordinates from `atomgroup` are optimally superimposed
        (translation and rotation) on the `reference` coordinates at each time step
        as to minimize the RMSD. Douglas Theobald's fast QCP algorithm
        [Theobald2005]_ is used for the rotational superposition and to calculate
        the RMSD (see :mod:`MDAnalysis.lib.qcprot` for implementation details).

        The class runs various checks on the input to ensure that the two atom
        groups can be compared. This includes a comparison of atom masses (i.e.,
        only the positions of atoms of the same mass will be considered to be
        correct for comparison). If masses should not be checked, just set
        `tol_mass` to a large value such as 1000.

        .. _ClustalW: http://www.clustal.org/
        .. _STAMP: http://www.compbio.dundee.ac.uk/manuals/stamp.4.2/


        See Also
        --------
        rmsd


        .. versionadded:: 0.7.7
        .. versionchanged:: 0.8
           `groupselections` added
        .. versionchanged:: 0.16.0
           Flexible weighting scheme with new `weights` keyword.
        .. deprecated:: 0.16.0
           Instead of ``mass_weighted=True`` (removal in 0.17.0) use new
           ``weights='mass'``; refactored to fit with AnalysisBase API
        .. versionchanged:: 0.17.0
           removed deprecated `mass_weighted` keyword; `groupselections`
           are *not* rotationally superimposed any more.
        .. deprecated:: 0.19.0
           `filename` will be removed in 1.0

        """
        super(RMSD, self).__init__(atomgroup.universe.trajectory,
                                   **kwargs)
        self.atomgroup = atomgroup
        self.reference = reference if reference is not None else self.atomgroup

        select = process_selection(select)
        self.groupselections = ([process_selection(s) for s in groupselections]
                                if groupselections is not None else [])
        self.weights = weights
        self.tol_mass = tol_mass
        self.ref_frame = ref_frame
        self.filename = filename   # DEPRECATED in 0.19.0, remove in 1.0.0

        self.ref_atoms = self.reference.select_atoms(*select['reference'])
        self.mobile_atoms = self.atomgroup.select_atoms(*select['mobile'])

        if len(self.ref_atoms) != len(self.mobile_atoms):
            err = ("Reference and trajectory atom selections do "
                   "not contain the same number of atoms: "
                   "N_ref={0:d}, N_traj={1:d}".format(self.ref_atoms.n_atoms,
                                                      self.mobile_atoms.n_atoms))
            logger.exception(err)
            raise SelectionError(err)
        logger.info("RMS calculation "
                    "for {0:d} atoms.".format(len(self.ref_atoms)))
        mass_mismatches = (np.absolute((self.ref_atoms.masses -
                                        self.mobile_atoms.masses)) >
                           self.tol_mass)

        if np.any(mass_mismatches):
            # diagnostic output:
            logger.error("Atoms: reference | mobile")
            for ar, at in zip(self.ref_atoms, self.mobile_atoms):
                if ar.name != at.name:
                    logger.error("{0!s:>4} {1:3d} {2!s:>3} {3!s:>3} {4:6.3f}"
                                 "|  {5!s:>4} {6:3d} {7!s:>3} {8!s:>3}"
                                 "{9:6.3f}".format(ar.segid, ar.resid,
                                                   ar.resname, ar.name,
                                                   ar.mass, at.segid, at.resid,
                                                   at.resname, at.name,
                                                   at.mass))
            errmsg = ("Inconsistent selections, masses differ by more than"
                      "{0:f}; mis-matching atoms"
                      "are shown above.".format(self.tol_mass))
            logger.error(errmsg)
            raise SelectionError(errmsg)
        del mass_mismatches

        # TODO:
        # - make a group comparison a class that contains the checks above
        # - use this class for the *select* group and the additional
        #   *groupselections* groups each a dict with reference/mobile
        self._groupselections_atoms = [
            {
                'reference': self.reference.universe.select_atoms(*s['reference']),
                'mobile': self.atomgroup.universe.select_atoms(*s['mobile']),
            }
            for s in self.groupselections]
        # sanity check
        for igroup, (sel, atoms) in enumerate(zip(self.groupselections,
                                                  self._groupselections_atoms)):
            if len(atoms['mobile']) != len(atoms['reference']):
                logger.exception('SelectionError: Group Selection')
                raise SelectionError(
                    "Group selection {0}: {1} | {2}: Reference and trajectory "
                    "atom selections do not contain the same number of atoms: "
                    "N_ref={3}, N_traj={4}".format(
                        igroup, sel['reference'], sel['mobile'],
                        len(atoms['reference']), len(atoms['mobile'])))

        # Explicitly check for "mass" because this option CAN
        # be used with groupselection. (get_weights() returns the mass array
        # for "mass")
        if not iterable(self.weights) and self.weights == "mass":
            pass
        else:
            self.weights = get_weights(self.mobile_atoms, self.weights)

        # cannot use arbitrary weight array (for superposition) with
        # groupselections because arrays will not match
        if (len(self.groupselections) > 0 and (
                iterable(self.weights) or self.weights not in ("mass", None))):
            raise ValueError("groupselections can only be combined with "
                             "weights=None or weights='mass', not a weight "
                             "array.")

        # initialized to note for testing the save function
        self.rmsd = None
示例#14
0
 def test_iterator(self):
     assert_equal(util.iterable(xrange(3)), True)
示例#15
0
 def test_tuples(self):
     assert_equal(util.iterable((1, 2, 3)), True)
     assert_equal(util.iterable(()), True)
示例#16
0
 def test_lists(self):
     assert_equal(util.iterable([1, 2, 3]), True)
     assert_equal(util.iterable([]), True)
示例#17
0
 def test_strings(self):
     """Test that iterable() works on any string (Fixed bug)"""
     assert_equal(util.iterable("byte string"), False)
     assert_equal(util.iterable(u"unicode string"), False)
示例#18
0
 def test_scalars(self):
     assert_equal(util.iterable(123), False)
示例#19
0
    def __init__(self,
                 atomgroup,
                 reference=None,
                 select='all',
                 groupselections=None,
                 filename="rmsd.dat",
                 weights=None,
                 tol_mass=0.1,
                 ref_frame=0,
                 **kwargs):
        # DEPRECATION: remove filename kwarg in 1.0
        r"""Parameters
        ----------
        atomgroup : AtomGroup or Universe
            Group of atoms for which the RMSD is calculated. If a trajectory is
            associated with the atoms then the computation iterates over the
            trajectory.
        reference : AtomGroup or Universe (optional)
            Group of reference atoms; if ``None`` then the current frame of
            `atomgroup` is used.
        select : str or dict or tuple (optional)
            The selection to operate on; can be one of:

            1. any valid selection string for
               :meth:`~MDAnalysis.core.groups.AtomGroup.select_atoms` that
               produces identical selections in `atomgroup` and `reference`; or

            2. a dictionary ``{'mobile': sel1, 'reference': sel2}`` where *sel1*
               and *sel2* are valid selection strings that are applied to
               `atomgroup` and `reference` respectively (the
               :func:`MDAnalysis.analysis.align.fasta2select` function returns such
               a dictionary based on a ClustalW_ or STAMP_ sequence alignment); or

            3. a tuple ``(sel1, sel2)``

            When using 2. or 3. with *sel1* and *sel2* then these selection strings
            are applied to `atomgroup` and `reference` respectively and should
            generate *groups of equivalent atoms*.  *sel1* and *sel2* can each also
            be a *list of selection strings* to generate a
            :class:`~MDAnalysis.core.groups.AtomGroup` with defined atom order as
            described under :ref:`ordered-selections-label`).

        groupselections : list (optional)
            A list of selections as described for `select`, with the difference
            that these selections are *always applied to the full universes*,
            i.e., ``atomgroup.universe.select_atoms(sel1)`` and
            ``reference.universe.select_atoms(sel2)``. Each selection describes
            additional RMSDs to be computed *after the structures have been
            superimposed* according to `select`. No additional fitting is
            performed.The output contains one additional column for each
            selection.

            .. Note:: Experimental feature. Only limited error checking
                      implemented.
        filename : str (optional)
            write RMSD into file with :meth:`RMSD.save`

            .. deprecated:; 0.19.0
               `filename` will be removed together with :meth:`save` in 1.0.

        weights : {"mass", ``None``} or array_like (optional)
             choose weights. With ``"mass"`` uses masses as weights; with ``None``
             weigh each atom equally. If a float array of the same length as
             `atomgroup` is provided, use each element of the `array_like` as a
             weight for the corresponding atom in `atomgroup`.
        tol_mass : float (optional)
             Reject match if the atomic masses for matched atoms differ by more
             than `tol_mass`.
        ref_frame : int (optional)
             frame index to select frame from `reference`
        verbose : bool (optional)
             Show detailed progress of the calculation if set to ``True``; the
             default is ``False``.

        Raises
        ------
        SelectionError
             If the selections from `atomgroup` and `reference` do not match.
        TypeError
             If `weights` is not of the appropriate type; see also
             :func:`MDAnalysis.lib.util.get_weights`
        ValueError
             If `weights` are not compatible with `atomgroup` (not the same
             length) or if it is not a 1D array (see
             :func:`MDAnalysis.lib.util.get_weights`).

             A :exc:`ValueError` is also raised if `weights` are not compatible
             with `groupselections`: only equal weights (``weights=None``) or
             mass-weighted (``weights="mass"``) are supported for additional
             `groupselections`.

        Notes
        -----
        The root mean square deviation :math:`\rho(t)` of a group of :math:`N`
        atoms relative to a reference structure as a function of time is
        calculated as

        .. math::

           \rho(t) = \sqrt{\frac{1}{N} \sum_{i=1}^N w_i \left(\mathbf{x}_i(t)
                                    - \mathbf{x}_i^{\text{ref}}\right)^2}

        The weights :math:`w_i` are calculated from the input weights `weights`
        :math:`w'_i` as relative to the mean of the input weights:

        .. math::

           w_i = \frac{w'_i}{\langle w' \rangle}

        The selected coordinates from `atomgroup` are optimally superimposed
        (translation and rotation) on the `reference` coordinates at each time step
        as to minimize the RMSD. Douglas Theobald's fast QCP algorithm
        [Theobald2005]_ is used for the rotational superposition and to calculate
        the RMSD (see :mod:`MDAnalysis.lib.qcprot` for implementation details).

        The class runs various checks on the input to ensure that the two atom
        groups can be compared. This includes a comparison of atom masses (i.e.,
        only the positions of atoms of the same mass will be considered to be
        correct for comparison). If masses should not be checked, just set
        `tol_mass` to a large value such as 1000.

        .. _ClustalW: http://www.clustal.org/
        .. _STAMP: http://www.compbio.dundee.ac.uk/manuals/stamp.4.2/


        See Also
        --------
        rmsd


        .. versionadded:: 0.7.7
        .. versionchanged:: 0.8
           `groupselections` added
        .. versionchanged:: 0.16.0
           Flexible weighting scheme with new `weights` keyword.
        .. deprecated:: 0.16.0
           Instead of ``mass_weighted=True`` (removal in 0.17.0) use new
           ``weights='mass'``; refactored to fit with AnalysisBase API
        .. versionchanged:: 0.17.0
           removed deprecated `mass_weighted` keyword; `groupselections`
           are *not* rotationally superimposed any more.
        .. deprecated:: 0.19.0
           `filename` will be removed in 1.0

        """
        super(RMSD, self).__init__(atomgroup.universe.trajectory, **kwargs)
        self.atomgroup = atomgroup
        self.reference = reference if reference is not None else self.atomgroup

        select = process_selection(select)
        self.groupselections = (
            [process_selection(s)
             for s in groupselections] if groupselections is not None else [])
        self.weights = weights
        self.tol_mass = tol_mass
        self.ref_frame = ref_frame
        self.filename = filename  # DEPRECATED in 0.19.0, remove in 1.0.0

        self.ref_atoms = self.reference.select_atoms(*select['reference'])
        self.mobile_atoms = self.atomgroup.select_atoms(*select['mobile'])

        if len(self.ref_atoms) != len(self.mobile_atoms):
            err = ("Reference and trajectory atom selections do "
                   "not contain the same number of atoms: "
                   "N_ref={0:d}, N_traj={1:d}".format(
                       self.ref_atoms.n_atoms, self.mobile_atoms.n_atoms))
            logger.exception(err)
            raise SelectionError(err)
        logger.info("RMS calculation "
                    "for {0:d} atoms.".format(len(self.ref_atoms)))
        mass_mismatches = (np.absolute(
            (self.ref_atoms.masses - self.mobile_atoms.masses)) >
                           self.tol_mass)

        if np.any(mass_mismatches):
            # diagnostic output:
            logger.error("Atoms: reference | mobile")
            for ar, at in zip(self.ref_atoms, self.mobile_atoms):
                if ar.name != at.name:
                    logger.error("{0!s:>4} {1:3d} {2!s:>3} {3!s:>3} {4:6.3f}"
                                 "|  {5!s:>4} {6:3d} {7!s:>3} {8!s:>3}"
                                 "{9:6.3f}".format(ar.segid, ar.resid,
                                                   ar.resname, ar.name,
                                                   ar.mass, at.segid, at.resid,
                                                   at.resname, at.name,
                                                   at.mass))
            errmsg = ("Inconsistent selections, masses differ by more than"
                      "{0:f}; mis-matching atoms"
                      "are shown above.".format(self.tol_mass))
            logger.error(errmsg)
            raise SelectionError(errmsg)
        del mass_mismatches

        # TODO:
        # - make a group comparison a class that contains the checks above
        # - use this class for the *select* group and the additional
        #   *groupselections* groups each a dict with reference/mobile
        self._groupselections_atoms = [{
            'reference':
            self.reference.universe.select_atoms(*s['reference']),
            'mobile':
            self.atomgroup.universe.select_atoms(*s['mobile']),
        } for s in self.groupselections]
        # sanity check
        for igroup, (sel, atoms) in enumerate(
                zip(self.groupselections, self._groupselections_atoms)):
            if len(atoms['mobile']) != len(atoms['reference']):
                logger.exception('SelectionError: Group Selection')
                raise SelectionError(
                    "Group selection {0}: {1} | {2}: Reference and trajectory "
                    "atom selections do not contain the same number of atoms: "
                    "N_ref={3}, N_traj={4}".format(igroup, sel['reference'],
                                                   sel['mobile'],
                                                   len(atoms['reference']),
                                                   len(atoms['mobile'])))

        # Explicitly check for "mass" because this option CAN
        # be used with groupselection. (get_weights() returns the mass array
        # for "mass")
        if not iterable(self.weights) and self.weights == "mass":
            pass
        else:
            self.weights = get_weights(self.mobile_atoms, self.weights)

        # cannot use arbitrary weight array (for superposition) with
        # groupselections because arrays will not match
        if (len(self.groupselections) > 0 and
            (iterable(self.weights) or self.weights not in ("mass", None))):
            raise ValueError("groupselections can only be combined with "
                             "weights=None or weights='mass', not a weight "
                             "array.")

        # initialized to note for testing the save function
        self.rmsd = None
示例#20
0
 def test_tuples(self):
     assert_equal(util.iterable((1, 2, 3)), True)
     assert_equal(util.iterable(()), True)
示例#21
0
 def test_arrays(self):
     assert_equal(util.iterable(np.array([1, 2, 3])), True)