def calc_covariance_matrix(coord=None, weights=None): """Calculate the covariance matrix for the structures. @keyword coord: The list of coordinates of all models to superimpose. The first index is the models, the second is the atomic positions, and the third is the xyz coordinates. @type coord: list of numpy rank-2, Nx3 arrays @keyword weights: The weights for each structure. @type weights: list of float @return: The covariance matrix and the deviation matrix. @rtype: numpy rank-2 3Nx3N array, numpy rank-2 MxNx3 array """ # Init. M = len(coord) N = len(coord[0]) if weights == None: weights = ones(M, float64) else: weights = array(weights, float64) covariance_matrix = zeros((N * 3, N * 3), float64) deviations = zeros((M, N, 3), float64) mean_struct = zeros((N, 3), float64) # Calculate the mean structure. calc_mean_structure(coord, mean_struct, weights=weights) # Loop over the models. for i in range(M): # The deviations from the mean. deviations[i] = coord[i] - mean_struct # Sum the covariance element. covariance_matrix += weights[i] * (outer(deviations[i], deviations[i])) # Average. covariance_matrix /= weights.sum() # Return the matrix. return covariance_matrix, deviations
def fit_to_mean(models=None, coord=None, centroid=None, verbosity=1): """Superimpose a set of structural models using the fit to first algorithm. @keyword models: The list of models to superimpose. @type models: list of int @keyword coord: The list of coordinates of all models to superimpose. The first index is the models, the second is the atomic positions, and the third is the xyz coordinates. @type coord: list of numpy rank-2, Nx3 arrays @keyword centroid: An alternative position of the centroid to allow for different superpositions, for example of pivot point motions. @type centroid: list of float or numpy rank-1, 3D array @keyword verbosity: The amount of information to print out. If 0, nothing will be printed. @type verbosity: int @return: The lists of translation vectors, rotation matrices, and rotation pivots. @rtype: list of numpy rank-1 3D arrays, list of numpy rank-2 3D arrays, list of numpy rank-1 3D arrays """ # Print out. if verbosity: print("\nSuperimposition of structural models %s using the 'fit to mean' algorithm." % models) # Duplicate the coordinates. orig_coord = deepcopy(coord) # Initialise the displacement lists. T_list = [] R_list = [] pivot_list = [] # Initialise the mean structure. N = len(coord[0]) mean = zeros((N, 3), float64) # Iterative fitting to mean. converged = False iter = 0 while not converged: # Print out. if verbosity: print("\nIteration %i of the algorithm." % iter) print("%-10s%-25s%-25s" % ("Model", "Translation (Angstrom)", "Rotation (deg)")) # Calculate the mean structure. calc_mean_structure(coord, mean) # Fit each model to the mean. converged = True for i in range(len(models)): # Calculate the displacements (Kabsch algorithm). trans_vect, trans_dist, R, axis, angle, pivot = kabsch(name_from='model %s'%models[0], name_to='mean', coord_from=coord[i], coord_to=mean, centroid=centroid, verbosity=0) # Table printout. if verbosity: print("%-10i%25.3g%25.3g" % (i, trans_dist, (angle / 2.0 / pi * 360.0))) # Shift the coordinates. for j in range(N): # Translate. coord[i][j] += trans_vect # The pivot to atom vector. coord[i][j] -= pivot # Rotation. coord[i][j] = dot(R, coord[i][j]) # The new position. coord[i][j] += pivot # Convergence test. if trans_dist > 1e-10 or angle > 1e-10: converged = False # Increment the iteration number. iter += 1 # Perform the fit once from the original coordinates to obtain the full transforms. for i in range(len(models)): # Calculate the displacements (Kabsch algorithm). trans_vect, trans_dist, R, axis, angle, pivot = kabsch(name_from='model %s'%models[i], name_to='the mean structure', coord_from=orig_coord[i], coord_to=mean, centroid=centroid, verbosity=0) # Store the transforms. T_list.append(trans_vect) R_list.append(R) pivot_list.append(pivot) # Return the transform data. return T_list, R_list, pivot_list
def fit_to_mean(models=None, coord=None, centre_type="centroid", elements=None, centroid=None, verbosity=1): """Superimpose a set of structural models using the fit to first algorithm. @keyword models: The list of models to superimpose. @type models: list of int @keyword coord: The list of coordinates of all models to superimpose. The first index is the models, the second is the atomic positions, and the third is the xyz coordinates. @type coord: list of numpy rank-2, Nx3 arrays @keyword centre_type: The type of centre to superimpose over. This can either be the standard centroid superimposition or the CoM could be used instead. @type centre_type: str @keyword elements: The list of elements corresponding to the atoms. @type elements: list of str @keyword centroid: An alternative position of the centroid to allow for different superpositions, for example of pivot point motions. @type centroid: list of float or numpy rank-1, 3D array @keyword verbosity: The amount of information to print out. If 0, nothing will be printed. @type verbosity: int @return: The lists of translation vectors, rotation matrices, and rotation pivots. @rtype: list of numpy rank-1 3D arrays, list of numpy rank-2 3D arrays, list of numpy rank-1 3D arrays """ # Print out. if verbosity: print( "\nSuperimposition of structural models %s using the 'fit to mean' algorithm." % models) # Duplicate the coordinates. orig_coord = deepcopy(coord) # Initialise the displacement lists. T_list = [] R_list = [] pivot_list = [] # Initialise the mean structure. N = len(coord[0]) mean = zeros((N, 3), float64) # Iterative fitting to mean. converged = False iter = 0 while not converged: # Print out. if verbosity: print("\nIteration %i of the algorithm." % iter) print("%-10s%-25s%-25s" % ("Model", "Translation (Angstrom)", "Rotation (deg)")) # Calculate the mean structure. calc_mean_structure(coord, mean) # Fit each model to the mean. converged = True for i in range(len(models)): # Calculate the displacements (Kabsch algorithm). trans_vect, trans_dist, R, axis, angle, pivot = kabsch( name_from='model %s' % models[0], name_to='mean', coord_from=coord[i], coord_to=mean, centre_type=centre_type, elements=elements, centroid=centroid, verbosity=0) # Table printout. if verbosity: print("%-10i%25.3g%25.3g" % (i, trans_dist, (angle / 2.0 / pi * 360.0))) # Shift the coordinates. for j in range(N): # Translate. coord[i][j] += trans_vect # The pivot to atom vector. coord[i][j] -= pivot # Rotation. coord[i][j] = dot(R, coord[i][j]) # The new position. coord[i][j] += pivot # Convergence test. if trans_dist > 1e-10 or angle > 1e-10: converged = False # Increment the iteration number. iter += 1 # Perform the fit once from the original coordinates to obtain the full transforms. for i in range(len(models)): # Calculate the displacements (Kabsch algorithm). trans_vect, trans_dist, R, axis, angle, pivot = kabsch( name_from='model %s' % models[i], name_to='the mean structure', coord_from=orig_coord[i], coord_to=mean, centre_type=centre_type, elements=elements, centroid=centroid, verbosity=0) # Store the transforms. T_list.append(trans_vect) R_list.append(R) pivot_list.append(pivot) # Return the transform data. return T_list, R_list, pivot_list