All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.biojava.nbio.structure.SVDSuperimposer Maven / Gradle / Ivy

There is a newer version: 7.2.2
Show newest version
/*
 *                  BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 *
 * Created on Dec 4, 2005
 *
 */
package org.biojava.nbio.structure;

import javax.vecmath.Matrix4d;

import org.biojava.nbio.structure.jama.Matrix;
import org.biojava.nbio.structure.jama.SingularValueDecomposition;


/** A class that calculates the superimposition between two sets of atoms
 * inspired by the biopython SVDSuperimposer class...
 *
 *
 * example usage:
 * 
			// get some arbitrary amino acids from somewhere
			String filename   =  "/Users/ap3/WORK/PDB/5pti.pdb" ;

			PDBFileReader pdbreader = new PDBFileReader();
			Structure struc = pdbreader.getStructure(filename);
			Group g1 = (Group)struc.getChain(0).getGroup(21).clone();
			Group g2 = (Group)struc.getChain(0).getGroup(53).clone();

			if ( g1.getPDBName().equals("GLY")){
				if ( g1 instanceof AminoAcid){
					Atom cb = Calc.createVirtualCBAtom((AminoAcid)g1);
					g1.addAtom(cb);
				}
			}

			if ( g2.getPDBName().equals("GLY")){
				if ( g2 instanceof AminoAcid){
					Atom cb = Calc.createVirtualCBAtom((AminoAcid)g2);
					g2.addAtom(cb);
				}
			}

			Structure struc2 = new StructureImpl((Group)g2.clone());

			System.out.println(g1);
			System.out.println(g2);


			Atom[] atoms1 = new Atom[3];
			Atom[] atoms2 = new Atom[3];

			atoms1[0] = g1.getAtom("N");
			atoms1[1] = g1.getAtom("CA");
			atoms1[2] = g1.getAtom("CB");


			atoms2[0] = g2.getAtom("N");
			atoms2[1] = g2.getAtom("CA");
			atoms2[2] = g2.getAtom("CB");


			SVDSuperimposer svds = new SVDSuperimposer(atoms1,atoms2);


			Matrix rotMatrix = svds.getRotation();
			Atom tranMatrix = svds.getTranslation();


			// now we have all the info to perform the rotations ...

			Calc.rotate(struc2,rotMatrix);

			//          shift structure 2 onto structure one ...
			Calc.shift(struc2,tranMatrix);

			//
			// write the whole thing to a file to view in a viewer

			String outputfile = "/Users/ap3/WORK/PDB/rotated.pdb";

			FileOutputStream out= new FileOutputStream(outputfile);
			PrintStream p =  new PrintStream( out );

			Structure newstruc = new StructureImpl();

			Chain c1 = new ChainImpl();
			c1.setName("A");
			c1.addGroup(g1);
			newstruc.addChain(c1);

			Chain c2 = struc2.getChain(0);
			c2.setName("B");
			newstruc.addChain(c2);

			// show where the group was originally ...
			Chain c3 = new ChainImpl();
			c3.setName("C");
			//c3.addGroup(g1);
			c3.addGroup(g2);

			newstruc.addChain(c3);
			p.println(newstruc.toPDB());

			p.close();

			System.out.println("wrote to file " + outputfile);

		
* * * @author Andreas Prlic * @since 1.5 * @version %I% %G% */ public class SVDSuperimposer { Matrix rot; Matrix tran; Matrix centroidA; Matrix centroidB; /** Create a SVDSuperimposer object and calculate a SVD superimposition of two sets of atoms. * * @param atomSet1 Atom array 1 * @param atomSet2 Atom array 2 * @throws StructureException */ public SVDSuperimposer(Atom[] atomSet1,Atom[]atomSet2) throws StructureException{ if ( atomSet1.length != atomSet2.length ){ throw new StructureException("The two atom sets are not of same length!"); } Atom cena = Calc.getCentroid(atomSet1); Atom cenb = Calc.getCentroid(atomSet2); double[][] centAcoords = new double[][]{{cena.getX(),cena.getY(),cena.getZ()}}; centroidA = new Matrix(centAcoords); double[][] centBcoords = new double[][]{{cenb.getX(),cenb.getY(),cenb.getZ()}}; centroidB = new Matrix(centBcoords); // center at centroid Atom[] ats1 = Calc.centerAtoms(atomSet1,cena); Atom[] ats2 = Calc.centerAtoms(atomSet2,cenb); double[][] coordSet1 = new double[ats1.length][3]; double[][] coordSet2 = new double[ats2.length][3]; // copy the atoms into the internal coords; for (int i =0 ; i< ats1.length;i++) { coordSet1[i] = ats1[i].getCoords(); coordSet2[i] = ats2[i].getCoords(); } calculate(coordSet1,coordSet2); } /** Do the actual calculation. * * @param coordSet1 coordinates for atom array 1 * @param coordSet2 coordiantes for atom array 2 */ private void calculate(double[][] coordSet1, double[][]coordSet2){ // now this is the bridge to the Jama package: Matrix a = new Matrix(coordSet1); Matrix b = new Matrix(coordSet2); // # correlation matrix Matrix b_trans = b.transpose(); Matrix corr = b_trans.times(a); SingularValueDecomposition svd = corr.svd(); Matrix u = svd.getU(); // v is alreaady transposed ! difference to numermic python ... Matrix vt =svd.getV(); Matrix vt_orig = (Matrix) vt.clone(); Matrix u_transp = u.transpose(); Matrix rot_nottrans = vt.times(u_transp); rot = rot_nottrans.transpose(); // check if we have found a reflection double det = rot.det(); if (det<0) { vt = vt_orig.transpose(); vt.set(2,0,(0 - vt.get(2,0))); vt.set(2,1,(0 - vt.get(2,1))); vt.set(2,2,(0 - vt.get(2,2))); Matrix nv_transp = vt.transpose(); rot_nottrans = nv_transp.times(u_transp); rot = rot_nottrans.transpose(); } Matrix cb_tmp = centroidB.times(rot); tran = centroidA.minus(cb_tmp); } /** Calculate the RMS (root mean square) deviation of two sets of atoms. * * Atom sets must be pre-rotated. * * @param atomSet1 atom array 1 * @param atomSet2 atom array 2 * @return the RMS of two atom sets * @throws StructureException */ public static double getRMS(Atom[] atomSet1, Atom[] atomSet2) throws StructureException { if ( atomSet1.length != atomSet2.length ){ throw new StructureException("The two atom sets are not of same length!"); } double sum = 0.0; for ( int i =0 ; i < atomSet1.length;i++){ double d = Calc.getDistance(atomSet1[i],atomSet2[i]); sum += (d*d); } double avd = ( sum/ atomSet1.length); //System.out.println("av dist" + avd); return Math.sqrt(avd); } /** * Calculate the TM-Score for the superposition. * * Normalizes by the minimum-length structure (that is, {@code min\{len1,len2\}}). * * Atom sets must be pre-rotated. * *

Citation:
* Zhang Y and Skolnick J (2004). "Scoring function for automated assessment * of protein structure template quality". Proteins 57: 702 - 710. * * @param atomSet1 atom array 1 * @param atomSet2 atom array 2 * @param len1 The full length of the protein supplying atomSet1 * @param len2 The full length of the protein supplying atomSet2 * @return The TM-Score * @throws StructureException */ public static double getTMScore(Atom[] atomSet1, Atom[] atomSet2, int len1, int len2) throws StructureException { if ( atomSet1.length != atomSet2.length ){ throw new StructureException("The two atom sets are not of same length!"); } if ( atomSet1.length > len1 ){ throw new StructureException("len1 must be greater or equal to the alignment length!"); } if ( atomSet2.length > len2 ){ throw new StructureException("len2 must be greater or equal to the alignment length!"); } int Lmin = Math.min(len1,len2); int Laln = atomSet1.length; double d0 = 1.24 * Math.cbrt(Lmin - 15.) - 1.8; double d0sq = d0*d0; double sum = 0; for(int i=0;iNormalizes by the maximum-length structure (that is, {@code max\{len1,len2\}}) rather than the minimum. * * Atom sets must be pre-rotated. * *

Citation:
* Zhang Y and Skolnick J (2004). "Scoring function for automated assessment * of protein structure template quality". Proteins 57: 702 - 710. * * @param atomSet1 atom array 1 * @param atomSet2 atom array 2 * @param len1 The full length of the protein supplying atomSet1 * @param len2 The full length of the protein supplying atomSet2 * @return The TM-Score * @throws StructureException * @see {@link #getTMScore(Atom[], Atom[], int, int)}, which normalizes by the minimum length */ public static double getTMScoreAlternate(Atom[] atomSet1, Atom[] atomSet2, int len1, int len2) throws StructureException { if ( atomSet1.length != atomSet2.length ){ throw new StructureException("The two atom sets are not of same length!"); } if ( atomSet1.length > len1 ){ throw new StructureException("len1 must be greater or equal to the alignment length!"); } if ( atomSet2.length > len2 ){ throw new StructureException("len2 must be greater or equal to the alignment length!"); } int Lmax = Math.max(len1,len2); int Laln = atomSet1.length; double d0 = 1.24 * Math.cbrt(Lmax - 15.) - 1.8; double d0sq = d0*d0; double sum = 0; for(int i=0;i





© 2015 - 2025 Weber Informatics LLC | Privacy Policy