Ejemplo n.º 1
0
 def addCoordset(self, coords, allcoordsets=True):
     """Add coordinate set(s) as conformation(s).
     :class:`~prody.atomic.Atomic` instances are accepted as *coords* 
     argument. If *allcoordsets* is ``True``, all coordinate sets from
     the :class:`~prody.atomic.Atomic` instance will be appended to the 
     ensemble. Otherwise, only the active coordinate set will be appended.
     """
     
     assert isinstance(allcoordsets, bool), 'allcoordsets must be boolean'
     if not isinstance(coords, np.ndarray):
         if isinstance(coords, (Atomic, Ensemble)):
             atoms = coords
             if allcoordsets:
                 coords = atoms.getCoordsets()
             else:
                 coords = atoms.getCoords()
             if coords is None:
                 raise ValueError('{0:s} must contain coordinate data'
                                  .format(atoms))
         else:
             raise TypeError('coords must be a Numpy array or '
                             'ProDy Atomic or Ensemble instance')
     
     coords = checkCoords(coords, arg='coords', cset=True, 
                          n_atoms=self._n_atoms, reshape=True)
     if self._n_atoms == 0:
         self._n_atoms = coords.shape[-2]
     n_confs = coords.shape[0]
         
     if self._confs is None: 
         self._confs = coords
     else:
         self._confs = np.concatenate((self._confs, coords), axis=0)
     self._n_csets += n_confs
Ejemplo n.º 2
0
    def addCoordset(self, coords, label=None):
        """Add a coordinate set.  *coords* argument may be an object instance 
        with ``getCoordsets`` method."""
        
        if not isinstance(coords, np.ndarray):
            coords = coords.getCoordsets()

        if self._coords is None:
            self.setCoords(coords)
            return

        coords = checkCoords(coords, 'coords', cset=True, 
                             n_atoms=self._n_atoms, reshape=True)
        diff = coords.shape[0]
        self._coords = np.concatenate((self._coords, coords), axis=0)
        self._n_csets = self._coords.shape[0]
        timestamps = self._timestamps
        self._timestamps = np.zeros(self._n_csets)
        self._timestamps[:len(timestamps)] = timestamps
        self._timestamps[len(timestamps):] = time()
        self._kdtrees.extend([None] * diff)
        if isinstance(label, (str, NoneType)):
            self._cslabels += [label] * diff
        elif isinstance(label, (list, tuple)):
            if len(label) == diff:
                if all([isinstance(lbl, str) for lbl in label]):
                    self._cslabels += label
                else:
                    LOGGER.warning('all items of `label` must be strings')
            else:
                LOGGER.warning('`label` list must have same length as the '
                               '`coords` array')
        else:
            LOGGER.warning('`label` must be a string or list of strings')
Ejemplo n.º 3
0
    def setCoords(self, coords):
        """Set reference coordinates."""

        if not isinstance(coords, np.ndarray):
            try:
                coords = coords.getCoords()
            except AttributeError:
                raise TypeError('coords must be a Numpy array or must have '
                                'getCoordinates attribute')
        self._coords = checkCoords(coords, arg='coords', 
                                   n_atoms=self._n_atoms, cset=False)
Ejemplo n.º 4
0
    def addCoordset(self, coords, weights=None, allcoordsets=True):
        """Add coordinate set(s) as conformation(s).

        :class:`~prody.atomic.Atomic` instances are accepted as *coords* 
        argument. If *allcoordsets* is ``True``, all coordinate sets from
        the :class:`~prody.atomic.Atomic` instance will be appended to the 
        ensemble. Otherwise, only the active coordinate set will be appended.

        *weights* is an optional argument. If provided, its length must
        match number of atoms. Weights of missing (not resolved) atoms 
        must be equal to ``0`` and weights of those that are resolved
        can be anything greater than ``0``. If not provided, weights of 
        atoms in this coordinate set will be set equal to ``1``."""
        
        assert isinstance(allcoordsets, bool), 'allcoordsets must be boolean'
        if weights is not None:
            assert isinstance(weights, np.ndarray), 'weights must be ndarray'
            
        ag = None
        if isinstance(coords, Atomic):
            atoms = coords
            if isinstance(coords, AtomGroup):
                ag = atoms
            else:
                ag = atoms.getAtomGroup()
            if allcoordsets:
                coords = atoms.getCoordsets()
            else: 
                coords = atoms.getCoords()
            title = ag.getTitle() 
        elif isinstance(coords, np.ndarray):
            title = 'Unknown'
        else:
            title = str(coords)
            try:
                if allcoordsets:
                    coords = coords.getCoordsets()
                else: 
                    coords = coords.getCoords()
            except AttributeError:            
                raise TypeError('coords must be a Numpy array or must have '
                                'getCoordinates attribute')

        coords = checkCoords(coords, 'coords', cset=True, 
                             n_atoms=self._n_atoms, reshape=True)
        n_csets, n_atoms, _ = coords.shape
        if self._n_atoms == 0:
            self._n_atoms = n_atoms
        if weights is None:
            weights = np.ones((n_csets, n_atoms, 1), dtype=float)
        else:
            weights = checkWeights(weights, n_atoms, n_csets)

        while '  ' in title:
            title = title.replace('  ', ' ')
        title = title.replace(' ', '_')
        
        if n_csets > 1:
            self._labels += ['{0:s}_{1:d}'
                                  .format(title, i+1) for i in range(n_csets)]
        else:
            if ag is not None and ag.numCoordsets() > 1:
                self._labels.append('{0:s}_{1:d}'.format(title, 
                                         atoms.getACSIndex()))
            else:                
                self._labels.append(title)
        if self._confs is None and self._weights is None:
            self._confs = coords
            self._weights = weights
            self._n_csets = n_csets
        elif self._confs is not None and self._weights is not None:
            self._confs = np.concatenate((self._confs, coords), axis=0)
            self._weights = np.concatenate((self._weights, weights), axis=0)
            self._n_csets += n_csets
        else:
            raise RuntimeError('_confs and _weights must be set or None at '
                               'the same time')
Ejemplo n.º 5
0
    def buildHessian(self, coords, cutoff=15.0, gamma=1.0, **kwargs):
        """Build Hessian matrix for given coordinate set.
        
        :arg coords: a coordinate set or anything with getCoordinates method
        :type coords: :class:`~numpy.ndarray` or :class:`~prody.atomic.Atomic`
        
        :arg cutoff: cutoff distance (Å) for pairwise interactions,
            default is 15.0 Å, minimum is 4.0 Å 
        :type cutoff: float
        
        :arg gamma: spring constant, default is 1.0 
        :type gamma: float, :class:`Gamma`
        
        :arg sparse: slect to use sparse matrices. Default is ``False``. If 
            Scipy is not found, :class:`ImportError` is raised.
        :type sparse: bool
        
        Instances of :class:`Gamma` classes and custom functions are
        accepted as *gamma* argument.        
    
        When Scipy is available, user can select to use sparse matrices for
        efficient usage of memory at the cost of computation speed."""

        slow = kwargs.get("slow", False)
        try:
            from KDTree import KDTree
        except ImportError:
            KDTree = False
        if not slow and not KDTree:
            LOGGER.info("Using a slower method for building the Hessian " "matrix.")
        if not isinstance(coords, np.ndarray):
            try:
                coords = coords.getCoords()
            except AttributeError:
                raise TypeError("coords must be a Numpy array or must have " "getCoordinates attribute")
        coords = checkCoords(coords, "coords")
        cutoff, g, gamma = checkENMParameters(cutoff, gamma)
        self._reset()
        self._cutoff = cutoff
        self._gamma = g
        n_atoms = coords.shape[0]
        dof = n_atoms * 3
        start = time.time()

        if kwargs.get("sparse", False):
            try:
                from scipy import sparse as scipy_sparse
            except ImportError:
                raise ImportError("failed to import scipy.sparse, which  is " "required for sparse matrix calculations")
            kirchhoff = scipy_sparse.lil_matrix((n_atoms, n_atoms))
            hessian = scipy_sparse.lil_matrix((dof, dof))
        else:
            kirchhoff = np.zeros((n_atoms, n_atoms), "d")
            hessian = np.zeros((dof, dof), float)
        if not slow and KDTree:
            kdtree = getKDTree(coords)
            kdtree.all_search(cutoff)
            for i, j in kdtree.all_get_indices():
                i2j = coords[j] - coords[i]
                dist2 = np.dot(i2j, i2j)
                g = gamma(dist2, i, j)
                super_element = np.outer(i2j, i2j) * (-g / dist2)
                res_i3 = i * 3
                res_i33 = res_i3 + 3
                res_j3 = j * 3
                res_j33 = res_j3 + 3
                hessian[res_i3:res_i33, res_j3:res_j33] = super_element
                hessian[res_j3:res_j33, res_i3:res_i33] = super_element
                hessian[res_i3:res_i33, res_i3:res_i33] = hessian[res_i3:res_i33, res_i3:res_i33] - super_element
                hessian[res_j3:res_j33, res_j3:res_j33] = hessian[res_j3:res_j33, res_j3:res_j33] - super_element
                kirchhoff[i, j] = -g
                kirchhoff[j, i] = -g
                kirchhoff[i, i] = kirchhoff[i, i] - g
                kirchhoff[j, j] = kirchhoff[j, j] - g
        else:
            cutoff2 = cutoff * cutoff
            for i in range(n_atoms):
                res_i3 = i * 3
                res_i33 = res_i3 + 3
                xyz_i = coords[i, :]
                for j in range(i + 1, n_atoms):
                    i2j = coords[j, :] - xyz_i
                    dist2 = np.dot(i2j, i2j)
                    if dist2 > cutoff2:
                        continue
                    g = gamma(dist2, i, j)
                    res_j3 = j * 3
                    res_j33 = res_j3 + 3
                    super_element = np.outer(i2j, i2j) * (-g / dist2)
                    hessian[res_i3:res_i33, res_j3:res_j33] = super_element
                    hessian[res_j3:res_j33, res_i3:res_i33] = super_element
                    hessian[res_i3:res_i33, res_i3:res_i33] = hessian[res_i3:res_i33, res_i3:res_i33] - super_element
                    hessian[res_j3:res_j33, res_j3:res_j33] = hessian[res_j3:res_j33, res_j3:res_j33] - super_element
                    kirchhoff[i, j] = -g
                    kirchhoff[j, i] = -g
                    kirchhoff[i, i] = kirchhoff[i, i] - g
                    kirchhoff[j, j] = kirchhoff[j, j] - g
        LOGGER.info("Hessian was built in {0:.2f}s.".format(time.time() - start))
        self._kirchhoff = kirchhoff
        self._hessian = hessian
        self._n_atoms = n_atoms
        self._dof = dof
Ejemplo n.º 6
0
    def setCoords(self, coords, label=None):
        """Set coordinates.  *coords* may be a :class:`numpy.ndarray` instance 
        or an object instance with ``getCoordsets`` method.  If the shape of 
        the coordinates array is (n_csets,n_atoms,3), the given array will 
        replace all coordinate sets.  To avoid it, :meth:`addCoordset` may be 
        used.  If the shape of the *coords* array is (n_atoms,3) or 
        (1,n_atoms,3), the coordinate set will replace the coordinates of the 
        currently active set.  *label* argument may be used to label coordinate
        sets.  *label* may be a string or a list of strings length equal to 
        the number of coordinate sets."""

        if not isinstance(coords, np.ndarray):
            coords = coords.getCoordsets()

        coords = checkCoords(coords, 'coords',
                                  cset=True, n_atoms=self._n_atoms,
                                  reshape=True)
        if self._n_atoms == 0:
            self._n_atoms = coords.shape[-2] 
            
        acsi = None
        if self._coords is None:
            self._coords = coords
            self._n_csets = coords.shape[0]
            self._acsi = 0
            self._setTimeStamp()
            if isinstance(label, (NoneType, str)):
                self._cslabels = [label] * self._n_csets
            elif isinstance(label, (list, tuple)):
                if len(label) == self._n_csets:
                    self._cslabels = label
                else:
                    self._cslabels = [None] * self._n_csets
                    LOGGER.warning('Length of `label` does not match number '
                                   'of coordinate sets.')
        else:
            if coords.shape[0] == 1:
                acsi = self._acsi
                self._coords[acsi] = coords[0]
                self._setTimeStamp(acsi)
                if isinstance(label, str):
                    self._cslabels[self._acsi] = label
            else:
                self._coords = coords
                self._n_csets = coords.shape[0]
                self._acsi = min(self._n_csets - 1, self._acsi)
                self._setTimeStamp()
                
        if acsi is None:
            if isinstance(label, (str, NoneType)):
                self._cslabels = [label] * self._n_csets
            elif isinstance(label, (list, tuple)):
                if len(label) == self._n_csets:
                    if all([isinstance(lbl, str) for lbl in label]):
                        self._cslabels += label
                    else:
                        LOGGER.warning('all items of label must be strings')
                else:
                    LOGGER.warning('label must have same length as the '
                                   'coords array')
            else:
                LOGGER.warning('label must be a string or list of strings')
                
        elif label is not None:
            if isinstance(label, str):
                self._cslabels[acsi] = label
            elif isinstance(label, (list, tuple)):
                if len(label) == 1:
                    if isinstance(label[0], str):
                        self._cslabels[acsi] = label
                    else:
                        LOGGER.warning('all items of label must be strings')
                else:
                    LOGGER.warning('length of label must be one')
            else:
                LOGGER.warning('label must be a string or list of strings')    
Ejemplo n.º 7
0
    def buildKirchhoff(self, coords, cutoff=10., gamma=1., **kwargs):
        """Build Kirchhoff matrix for given coordinate set.
        
        :arg coords: a coordinate set or anything with getCoordinates method
        :type coords: :class:`~numpy.ndarray` or :class:`~prody.atomic.Atomic`
        
        :arg cutoff: cutoff distance (Å) for pairwise interactions
            default is 10.0 Å, , minimum is 4.0 Å
        :type cutoff: float
        
        :arg gamma: spring constant, default is 1.0
        :type gamma: float
        
        :arg sparse: Elect to use sparse matrices. Default is ``False``. If 
            Scipy is not found, :class:`ImportError` is raised.
        :type sparse: bool
        
        Instances of :class:`Gamma` classes and custom functions are
        accepted as *gamma* argument.        

        When Scipy is available, user can select to use sparse matrices for
        efficient usage of memory at the cost of computation speed."""
        
        slow = kwargs.get('slow', False)
        try:
            from KDTree import KDTree
        except ImportError:
            KDTree = False
        if not slow and not KDTree: 
            LOGGER.info('Using a slower method for building the Kirchhoff '
                         'matrix.')
        if not isinstance(coords, np.ndarray):
            try:
                coords = coords.getCoords()
            except AttributeError:
                raise TypeError('coords must be a Numpy array or must have '
                                'getCoordinates attribute')
        coords = checkCoords(coords, 'coords')
        cutoff, g, gamma = checkENMParameters(cutoff, gamma)
        self._reset()
        self._cutoff = cutoff
        self._gamma = g
                    
        n_atoms = coords.shape[0]
        start = time.time()
        if kwargs.get('sparse', False):
            try:
                from scipy import sparse as scipy_sparse
            except ImportError:    
                raise ImportError('failed to import scipy.sparse, which  is '
                                  'required for sparse matrix calculations')
            kirchhoff = scipy_sparse.lil_matrix((n_atoms, n_atoms))
        else:
            kirchhoff = np.zeros((n_atoms, n_atoms), 'd')
        
        if not slow and KDTree:
            kdtree = getKDTree(coords) 
            kdtree.all_search(cutoff)
            radii = kdtree.all_get_radii()
            r = 0
            for i, j in kdtree.all_get_indices():
                g = gamma(radii[r]**2, i, j)
                kirchhoff[i, j] = -g
                kirchhoff[j, i] = -g
                kirchhoff[i, i] = kirchhoff[i, i] + g
                kirchhoff[j, j] = kirchhoff[j, j] + g
                r += 1
        else:
            cutoff2 = cutoff * cutoff
            for i in range(n_atoms):
                xyz_i = coords[i, :]
                for j in range(i+1, n_atoms):
                    i2j = coords[j, :] - xyz_i
                    dist2 = np.dot(i2j, i2j)
                    if dist2 > cutoff2:
                        continue             
                    g = gamma(dist2, i, j)
                    kirchhoff[i, j] = -g
                    kirchhoff[j, i] = -g
                    kirchhoff[i, i] = kirchhoff[i, i] + g
                    kirchhoff[j, j] = kirchhoff[j, j] + g
            
        LOGGER.debug('Kirchhoff was built in {0:.2f}s.'
                     .format(time.time()-start))
        self._kirchhoff = kirchhoff
        self._n_atoms = n_atoms
        self._dof = n_atoms
Ejemplo n.º 8
0
    def write(self, coords, unitcell=None, **kwargs):
        """Write *coords* to the file.  Number of atoms will be determined 
        based on the size of the first coordinate set.  If *unitcell* is 
        provided for the first coordinate set, it will be expected for the
        following coordinate sets as well.
        
        The following keywords are used when writing the first coordinate set 
        for files open at 'w' mode:        
            
        :arg timestep: timestep used for integration, default is 1
        :arg firsttimestep: number of the first timestep, default is 0
        :arg framefreq: number of timesteps between frames, default is 1"""
        
        if self._closed:
            raise ValueError('I/O operation on closed file')
        if self._mode == 'r':
            raise IOError('File not open for writing')
        coords = checkCoords(coords, 'coords', True, dtype=np.float32)
        if coords.ndim == 2:
            n_atoms = coords.shape[0]
            coords = [coords]
        else:
            n_atoms = coords.shape[1]
        if self._n_atoms == 0:
            self._n_atoms = n_atoms
        else:
            if self._n_atoms != n_atoms:
                raise ValueError('coords to not have correct number '
                                 'of atoms')
        dcd = self._file
        pack_i_4N = pack('i', self._n_atoms * 4)
        if self._n_csets == 0:
            if unitcell is None:
                self._unitcell = False
            else:
                self._unitcell = True
            timestep = float(kwargs.get('timestep', 1.0))
            first_ts = int(kwargs.get('firsttimestep', 0))
            framefreq = int(kwargs.get('framefreq', 1))
            n_fixed = 0

            pack_i_0 = pack('i', 0)
            pack_ix4_0x4 = pack('i'*4, 0, 0, 0, 0)
            pack_i_1 = pack('i', 1)
            pack_i_2 = pack('i', 2)
            pack_i_4 = pack('i', 4)
            pack_i_84 = pack('i', 84)
            pack_i_164 = pack('i', 164)

            dcd.write(pack_i_84)
            dcd.write('CORD')
            dcd.write(pack_i_0) # 0 Number of frames in file, none written yet
            dcd.write(pack('i', first_ts)) # 1 Starting timestep
            dcd.write(pack('i', framefreq)) # 2 Timesteps between frames
            dcd.write(pack_i_0) # 3 Number of timesteps in simulation
            dcd.write(pack_i_0) # 4 NAMD writes NSTEP or ISTART - NSAVC here?
            dcd.write(pack_ix4_0x4) # 5, 6, 7, 8
            dcd.write(pack('f', timestep)) # 9 timestep
            dcd.write(pack('i', int(self._unitcell))) # 10 with unitcell
            dcd.write(pack_ix4_0x4) # 11, 12, 13, 14
            dcd.write(pack_ix4_0x4) # 15, 16, 17, 18
            dcd.write(pack('i', 24)) # 19 Pretend to be CHARMM version 24
            dcd.write(pack_i_84)
            dcd.write(pack_i_164)
            dcd.write(pack_i_2)
            dcd.write('{0:80s}'.format('Created by ProDy'))
            dcd.write('{0:80s}'.format('REMARKS Created ' + 
                                       now().strftime('%d %B, %Y at %H:%M')))
            dcd.write(pack_i_164)
            
            dcd.write(pack_i_4)
            dcd.write(pack('i', n_atoms))
            dcd.write(pack_i_4)
            self._first_byte = dcd.tell()
        if self._unitcell: 
            if unitcell is None:
                raise TypeError('unitcell data is expected')
            else:
                uc = unitcell
                uc[3:] = np.sin((PISQUARE/90) * (90-uc[3:]))
                uc = uc[[0,3,1,4,5,2]]
                pack_i_48 = pack('i', 48)
        dcd.seek(0, 2)
        for xyz in coords:
            if self._unitcell:
                dcd.write(pack_i_48)
                uc.tofile(dcd)
                dcd.write(pack_i_48)
            xyz = xyz.T
            dcd.write(pack_i_4N)
            xyz[0].tofile(dcd)
            dcd.write(pack_i_4N)
            dcd.write(pack_i_4N)
            xyz[1].tofile(dcd)
            dcd.write(pack_i_4N)
            dcd.write(pack_i_4N)
            xyz[2].tofile(dcd)
            dcd.write(pack_i_4N)
            self._n_csets += 1
            dcd.seek(8, 0)
            dcd.write(pack('i', self._n_csets))
            dcd.seek(0, 2)
        self._nfi = self._n_csets