def iterativeSuperposition(self):
        """
        Calculates an iterative superposition of a set of conformations. When using this function,
        the input coordinates are changed (it wouldn't have too much sense otherwise).
        In this case calculation coordinates are not used as such, but as a secondary coordinates set
        that is rotate along with the primary fitting set (which allows to use different selections
        to do the iterative fit and any other calculation). Fit symmetry groups have no effect in iterative
        superposition.

        @author: vgil
        @date: 27/03/2013
        """
        np_coords_fit, np_coords_calc = self.__coords_reshaping()

        pyRMSD.calculators.iterativeSuperposition(
            availableCalculators()[self.calculator_type],
            np_coords_fit,
            self.number_of_fitting_atoms,
            np_coords_calc,
            self.number_of_calculation_atoms,
            self.number_of_conformations,
            self.calc_symmetry_groups,
            self.__number_of_threads,
            self.__threads_per_block,
            self.__blocks_per_grid,
        )

        return numpy.reshape(np_coords_fit, (self.number_of_conformations, self.number_of_fitting_atoms, 3))
Example #2
0
 def oneVsFollowing(self, conformation_number):
     """
     Calculates the RMSD between a reference conformation and all other conformations with an id greater than it.
     
     @param conformation_number: The id of the reference structure.
     
     @return: A numpy array of RMSD values.
     
     @author: vgil
     @date: 26/11/2012
     """
     np_coords_fit, np_coords_calc = self.__coords_reshaping()
     
     rmsds =  pyRMSD.calculators.oneVsFollowing(availableCalculators()[self.calculator_type], 
                                                  np_coords_fit, 
                                                  self.number_of_fitting_atoms, 
                                                  np_coords_calc, 
                                                  self.number_of_calculation_atoms,
                                                  conformation_number, 
                                                  self.number_of_conformations,
                                                  self.symmetry_groups,
                                                  self.__number_of_threads, 
                                                  self.__threads_per_block, 
                                                  self.__blocks_per_grid)
     return rmsds
    def pairwiseRMSDMatrix(self):
        """
        Calculates the pairwise RMSD matrix for all conformations in the coordinates set.

        @return: A numpy array with the upper triangle of the matrix, in row major format.

        @author: vgil
        @date: 26/11/2012
        """
        np_coords_fit, np_coords_calc = self.__coords_reshaping()

        rmsd_values = pyRMSD.calculators.calculateRMSDCondensedMatrix(
            availableCalculators()[self.calculator_type],
            np_coords_fit,
            self.number_of_fitting_atoms,
            np_coords_calc,
            self.number_of_calculation_atoms,
            self.number_of_conformations,
            self.calc_symmetry_groups,
            self.__number_of_threads,
            self.__threads_per_block,
            self.__blocks_per_grid,
        )

        # It has been necessary to add this hack to the function. When using symmetries, in one Test case,
        # the only way to make it work was to add this list() hack and changing return PyArray_Return(rmsds_list_obj);
        # by Py_INCREF(rmsds_list_obj); + return (PyObject*) rmsds_list_obj; in calculateRMSDCondensedMatrix
        # This problem only happens in some cases and I've been unable to guess why.
        # The error says: SystemError: ../Objects/listobject.c:169: bad argument to internal function
        return list(rmsd_values)
def do_math(datadir, reference, outputdir):   
    # Use CUDA for GPU calculations, if avialable
    if 'QCP_CUDA_MEM_CALCULATOR' in availableCalculators():
        pyrmsd_calc = 'QCP_CUDA_MEM_CALCULATOR'
    else:
        pyrmsd_calc = 'QCP_SERIAL_CALCULATOR'
        
    input_temp = []
    for i in os.listdir(outputdir):
        if i.endswith('.pdb'):
            input_temp.append(os.path.join(outputdir, i ))
    input_pdbs = sorted(input_temp)
    
    #neighbors = find_neighbors(datadir, reference, 8)
    
    #point_mutants = mutant_rms(datadir, input_pdbs)
    neighborhood = neighborhood_rms(neighbors, reference, input_pdbs)
    global_ca = global_ca_rms(input_pdbs)

    return_output_dict = {}

    #return_output_dict['Point Mutant RMSDs'] = rmsd(input_pdbs, pyrmsd_calc, point_mutants)
    #return_output_dict['Neighborhood RMSD'] = rmsd(input_pdbs, pyrmsd_calc, neighborhood)
    return_output_dict['Global RMSD'] = rmsd(input_pdbs, pyrmsd_calc, global_ca)
    #chi_angles_output = chi_angles(datadir, input_pdbs)
    #if chi_angles_output != {}:
    #    return_output_dict['X angles'] = chi_angles_output
    #else:
    #    print 'No X angles!'
    return return_output_dict
Example #5
0
 def pairwiseRMSDMatrix(self):
     """
     Calculates the pairwise RMSD matrix for all conformations in the coordinates set.
     
     @return: A numpy array with the upper triangle of the matrix, in row major format.
     
     @author: vgil
     @date: 26/11/2012
     """
     np_coords_fit, np_coords_calc = self.__coords_reshaping()
     
     rmsd_values = pyRMSD.calculators.calculateRMSDCondensedMatrix(availableCalculators()[self.calculator_type], 
                                                            np_coords_fit, 
                                                            self.number_of_fitting_atoms, 
                                                            np_coords_calc, 
                                                            self.number_of_calculation_atoms,
                                                            self.number_of_conformations,
                                                            self.symmetry_groups,
                                                            self.__number_of_threads, 
                                                            self.__threads_per_block, 
                                                            self.__blocks_per_grid)
     return rmsd_values
def do_math( reference, outputdir, predID):
    # Use CUDA for GPU calculations, if avialable
    if 'QCP_CUDA_MEM_CALCULATOR' in availableCalculators():
        pyrmsd_calc = 'QCP_CUDA_MEM_CALCULATOR'
    else:
        pyrmsd_calc = 'QCP_SERIAL_CALCULATOR'
        
    input_temp = []

    for app_output_dir in os.listdir(outputdir):
        for app_outfile in os.listdir(os.path.join(outputdir, app_output_dir)):
            #Mutant Structures
            if app_outfile == 'min_cst.mutate_bkrb_min_cst_0001_0001.pdb.gz':
                input_temp.append(os.path.join(outputdir, app_output_dir, app_outfile))
                input_pdbs = sorted(input_temp)
            # WT Structures
            #if app_outfile == 'min_cst.repack-wt_bkrb_min_cst_0001_0001.pdb.gz':
            #    input_temp.append(os.path.join(outputdir, app_output_dir, app_outfile ))
            #    input_pdbs = sorted(input_temp)

    mutations, fresh_pdb = Fetch_PredID_Info(predID)

    point_mutants = mutant_coordinates(input_pdbs, predID, mutations, fresh_pdb)
    neighbors = find_neighbors( reference, predID, mutations, fresh_pdb, 8)
    neighborhood = neighborhood_coordinates(neighbors, reference, input_pdbs)
    global_ca = global_ca_coordinates(input_pdbs)

    return_output_dict = {}

    return_output_dict['Point Mutant RMSDs'] = rmsd( pyrmsd_calc, point_mutants)
    return_output_dict['Neighborhood RMSD'] = rmsd(pyrmsd_calc, neighborhood)
    return_output_dict['Global RMSD'] = rmsd(pyrmsd_calc, global_ca)
    chi_angles_output = chi_angles(input_pdbs, predID, mutations, fresh_pdb)
    if chi_angles_output != {}:
        return_output_dict['X angles'] = chi_angles_output
    else:
        print 'No X angles!'
    return return_output_dict
Example #7
0
 def __init__(self, calculatorType, 
              fittingCoordsets, 
              calculationCoordsets = None, 
              symmetryGroups = []):
     """
     Class constructor.
     
     @param calculatorType: One of the calculators returned by 'availableCalculators()'. i.e. KABSCH_OMP_CALCULATOR
     
     @param fittingCoordsets: An array containing the used coordinates of each conformation. It has the following form:
         coordsets: [Conformation 1, Conformation 2, ..., Conformation N]
         Conformation: [Atom 1, Atom 2,..., Atom M]
         Atom: [x,y,z]
         
         This coordinates will be used for both structural superposition and RMSD calculation if the 'calculation 
         coordinates' parameter is not defined.
         
         The array type is constrained to be a numpy.array object with dtype = numpy.float64 (dtype will not be always double
         by default).
         
         Input coordinates are modified after each operation (usually centered and superposed into reference conformation).
     
     @param calculationCoordsets: An array containing the coordinates used to calculate the RMSD. Must have the same structure 
         than 'fittingCoordinates'.
     
     @param symmetryGroups: List of symmetry groups. Each symmetry group is a 2-Tuple of n-tuples defining interchangeable positions
         of current calculation coordinates (which will be the fitting coordinates, or the calculation coordinates if defined). 
         For instance, given a calculator with this fitting coordinates (without calculation coordinates):
              a,  b,  c,  d,  e , f ;  for conf1
              a1, b1, c3, d4, e5, f6 ; for conf2
              a2, b2, c3, d4, e5, f6 ; for conf3
         
         and a symmetry group definition [((1,3),(2,4)),]. The final RMSDs would be the minimum RMSDs of:
             a,  b,  c,  d,  e , f ;  for conf1 (original)
             a,  c,  b,  e,  d , f ;  for conf1 (applying symmetry group)
         
         with:
             a1, b1, c3, d4, e5, f6 ; for conf2
             a2, b2, c3, d4, e5, f6 ; for conf3
             
         Symm. groups are a low-level structure-agnostic of the type of symmetries that can be found in some ligands, 
         i.e. in rotating benzene groups. It can also be used in symmetries of bigger selections though. 
         
     @author: vgil
     @date: 26/11/2012
     """
     if not calculatorType in availableCalculators():
         print "Calculator ", calculatorType, " is not an available calculator."
         raise ValueError
     else:
         self.fitting_coordinates = fittingCoordsets
         self.calculator_type = calculatorType
         self.number_of_conformations = self.fitting_coordinates.shape[0]
         self.number_of_fitting_atoms = self.fitting_coordinates.shape[1]
         
         self.calculation_coordinates = calculationCoordsets
         if self.calculation_coordinates is not None:
             self.calculation_coordinates = calculationCoordsets
             if self.number_of_conformations != self.calculation_coordinates.shape[0]:
                 print "Calculation coordinates must hold the same number of conformations than fitting coordinates."
                 raise ValueError
             self.number_of_calculation_atoms = self.calculation_coordinates.shape[1]
         else:
             self.number_of_calculation_atoms = 0
         
         # Default values for openMP and CUDA flags
         self.__threads_per_block = 32
         self.__blocks_per_grid = 8
         self.__number_of_threads = 8
         
         # Symmetry group handling
         self.__check_symm_groups(symmetryGroups)
         self.symmetry_groups = symmetryGroups
Example #8
0
import pyRMSD
from pyRMSD.matrixHandler import MatrixHandler
import pyRMSD.RMSDCalculator
from pyRMSD.availableCalculators import availableCalculators
# Use CUDA for GPU calculations, if avialable
if 'QCP_CUDA_MEM_CALCULATOR' in availableCalculators():
    pyrmsd_calc = 'QCP_CUDA_MEM_CALCULATOR'
else:
    pyrmsd_calc = 'QCP_SERIAL_CALCULATOR'

import pyRMSD
import prody
import os
import numpy as np
import scipy.spatial.distance

def pairwise_rmsd(input_pdbs):
    coordinates = np.array( [prody.parsePDB(input_pdb).select('calpha').getCoords() for input_pdb in input_pdbs] )

    rmsd_matrix = pyRMSD.matrixHandler.MatrixHandler().createMatrix(coordinates, pyrmsd_calc)
    print scipy.spatial.distance.squareform( rmsd_matrix.get_data() )


if __name__ == '__main__':
    pdb_dir = os.path.join('..', '..', '.testdata','pdbs')
    input_pdbs = sorted( [os.path.join(pdb_dir, f ) for f in os.listdir(pdb_dir)] )
    pairwise_rmsd( input_pdbs[:2] )
    def oneVsFollowing(self, conformation_number):
        """
        Calculates the RMSD between a reference conformation and all other conformations with an id greater than it.
        If fitting symmetry groups are used, input coordinates won't be modified (as it works with coordinate copies).

        @param conformation_number: The id of the reference structure.

        @return: A numpy array of RMSD values.

        @author: vgil
        @date: 26/11/2012
        """
        np_coords_fit, np_coords_calc = self.__coords_reshaping()

        if self.fit_symmetry_groups == []:
            rmsds = pyRMSD.calculators.oneVsFollowing(
                availableCalculators()[self.calculator_type],
                np_coords_fit,
                self.number_of_fitting_atoms,
                np_coords_calc,
                self.number_of_calculation_atoms,
                conformation_number,
                self.number_of_conformations,
                self.calc_symmetry_groups,
                self.__number_of_threads,
                self.__threads_per_block,
                self.__blocks_per_grid,
            )
        else:
            # If we have fitting symmetry groups, we have to try with all possible combinations.
            # Calculation symmetry groups are applied at C level, changing the way RMSD is calculated.
            symm_rmsds = []
            for permutation in symm_permutations(self.fit_symmetry_groups):

                # Copy the coordinates and convert to matrix form for ease of indexing
                coords_copy = numpy.array(np_coords_fit, copy=True, dtype=numpy.float64)
                coords_copy.shape = (self.number_of_conformations, self.number_of_fitting_atoms, 3)

                # Apply the changes to reference
                for symm_group in permutation:
                    # Do it only if the symm. group is not permuted. Otherwise we would always permute!
                    if not symm_group in self.fit_symmetry_groups:
                        for symm_pair in symm_group:
                            swap_atoms(coords_copy[conformation_number], symm_pair[0], symm_pair[1])

                # Flatten again to feed the C calculator
                coords_copy.shape = self.number_of_conformations * self.number_of_fitting_atoms * 3

                # And calculate the RMSD of this permutation
                symm_rmsds.append(
                    pyRMSD.calculators.oneVsFollowing(
                        availableCalculators()[self.calculator_type],
                        coords_copy,
                        self.number_of_fitting_atoms,
                        np_coords_calc,
                        self.number_of_calculation_atoms,
                        conformation_number,
                        self.number_of_conformations,
                        self.calc_symmetry_groups,
                        self.__number_of_threads,
                        self.__threads_per_block,
                        self.__blocks_per_grid,
                    )
                )
            # Pick the minimum rmsd of all possibilities.
            rmsds = min_rmsd_of_rmsds_list(numpy.array(symm_rmsds))

        return rmsds
    def __init__(
        self, calculatorType, fittingCoordsets, calculationCoordsets=None, fitSymmetryGroups=[], calcSymmetryGroups=[]
    ):
        """
        Class constructor.

        @param calculatorType: One of the calculators returned by 'availableCalculators()'. i.e. KABSCH_OMP_CALCULATOR

        @param fittingCoordsets: An array containing the used coordinates of each conformation. It has the following form:
            coordsets: [Conformation 1, Conformation 2, ..., Conformation N]
            Conformation: [Atom 1, Atom 2,..., Atom M]
            Atom: [x,y,z]

            This coordinates will be used for both structural superposition and RMSD calculation if the 'calculation
            coordinates' parameter is not defined.

            The array type is constrained to be a numpy.array object with dtype = numpy.float64 (dtype will not be always double
            by default).

            Input coordinates are modified after each operation (usually centered and superposed into reference conformation).

        @param calculationCoordsets: An array containing the coordinates used to calculate the RMSD. Must have the same structure
            than 'fittingCoordinates'.

        @param fitSymmetryGroups: List of symmetry groups. 
            Symm. groups are a low-level structure-agnostic of the type of symmetries that can be found in some ligands,
            i.e. in rotating benzene groups. It can also be used in symmetries of bigger selections though.
            See :py:func:`pyRMSD.symmTools.symm_permutations` 
        @param calcSymmetryGroups: As in 'fitSymmetryGroups', a list of symmetry groups.

        @author: vgil
        @date: 26/11/2012
        """
        if not calculatorType in availableCalculators():
            print "Calculator ", calculatorType, " is not an available calculator."
            raise ValueError
        else:
            self.fitting_coordinates = fittingCoordsets
            self.calculator_type = calculatorType
            self.number_of_conformations = self.fitting_coordinates.shape[0]
            self.number_of_fitting_atoms = self.fitting_coordinates.shape[1]

            self.calculation_coordinates = calculationCoordsets
            if self.calculation_coordinates is not None:
                self.calculation_coordinates = calculationCoordsets
                if self.number_of_conformations != self.calculation_coordinates.shape[0]:
                    print "Calculation coordinates must hold the same number of conformations than fitting coordinates."
                    raise ValueError
                self.number_of_calculation_atoms = self.calculation_coordinates.shape[1]
            else:
                self.number_of_calculation_atoms = 0

            # Default values for openMP and CUDA flags
            self.__threads_per_block = 32
            self.__blocks_per_grid = 8
            self.__number_of_threads = 8

            # Symmetry group handling
            symm_groups_validation(fitSymmetryGroups)
            symm_groups_validation(calcSymmetryGroups)
            self.fit_symmetry_groups = fitSymmetryGroups
            self.calc_symmetry_groups = calcSymmetryGroups