001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.align.gui;
022
023import java.util.List;
024
025import org.biojava.nbio.structure.Atom;
026import org.biojava.nbio.structure.AtomImpl;
027import org.biojava.nbio.structure.Calc;
028import org.biojava.nbio.structure.Group;
029import org.biojava.nbio.structure.StructureException;
030import org.biojava.nbio.structure.StructureTools;
031import org.biojava.nbio.structure.align.AFPTwister;
032import org.biojava.nbio.structure.align.fatcat.FatCatFlexible;
033import org.biojava.nbio.structure.align.fatcat.FatCatRigid;
034import org.biojava.nbio.structure.align.gui.jmol.StructureAlignmentJmol;
035import org.biojava.nbio.structure.align.model.AFPChain;
036import org.biojava.nbio.structure.jama.Matrix;
037
038public class StructureAlignmentDisplay {
039
040        /** Display an AFPChain alignment
041         *
042         * @param afpChain
043         * @param ca1
044         * @param ca2
045         * @return a StructureAlignmentJmol instance
046         * @throws StructureException
047         */
048        public static StructureAlignmentJmol display(AFPChain afpChain, Atom[] ca1, Atom[] ca2) throws StructureException {
049
050                if ( ca1.length < 1 || ca2.length < 1){
051                        throw new StructureException("length of atoms arrays is too short! " + ca1.length + "," + ca2.length);
052                }
053
054                Group[] twistedGroups = prepareGroupsForDisplay(afpChain, ca1, ca2);
055
056                List<Group> hetatms  = StructureTools.getUnalignedGroups(ca1);
057                List<Group> hetatms2 = StructureTools.getUnalignedGroups(ca2);
058
059                return DisplayAFP.display(afpChain, twistedGroups, ca1, ca2, hetatms, hetatms2);
060
061        }
062
063        /** Rotate the Atoms/Groups so they are aligned for the 3D visualisation
064         *
065         * @param afpChain
066         * @param ca1
067         * @param ca2
068         * @return an array of Groups that are transformed for 3D display
069         * @throws StructureException
070         */
071        public static Group[] prepareGroupsForDisplay(AFPChain afpChain, Atom[] ca1, Atom[] ca2) throws StructureException{
072
073
074                if ( afpChain.getBlockRotationMatrix().length == 0 ) {
075                        // probably the alignment is too short!
076                        System.err.println("No rotation matrix found to rotate 2nd structure!");
077                        afpChain.setBlockRotationMatrix(new Matrix[]{Matrix.identity(3, 3)});
078                        afpChain.setBlockShiftVector(new Atom[]{new AtomImpl()});
079                }
080
081                // List of groups to be rotated according to the alignment
082                Group[] twistedGroups = new Group[ ca2.length];
083
084                //int blockNum = afpChain.getBlockNum();
085
086                int i = -1;
087
088                // List of groups from the structure not included in ca2 (e.g. ligands)
089                // Will be rotated according to first block
090                List<Group> hetatms2 = StructureTools.getUnalignedGroups(ca2);
091
092                if (  (afpChain.getAlgorithmName().equals(FatCatRigid.algorithmName) ) || (afpChain.getAlgorithmName().equals(FatCatFlexible.algorithmName) ) ){
093
094                        for (Atom a: ca2){
095                                i++;
096                                twistedGroups[i]=a.getGroup();
097
098                        }
099
100                        twistedGroups = AFPTwister.twistOptimized(afpChain, ca1, ca2);
101
102                //} else  if  (( blockNum == 1 ) || (afpChain.getAlgorithmName().equals(CeCPMain.algorithmName))) {
103                } else {
104
105                        Matrix m   =  afpChain.getBlockRotationMatrix()[ 0];
106                        Atom shift =  afpChain.getBlockShiftVector()   [ 0 ];
107
108                        shiftCA2(afpChain, ca2, m,shift, twistedGroups);
109
110                }
111
112                if ( afpChain.getBlockNum() > 0){
113
114                        // Superimpose ligands relative to the first block
115                        if( hetatms2.size() > 0 ) {
116
117                                if ( afpChain.getBlockRotationMatrix().length > 0 ) {
118
119                                        Matrix m1      = afpChain.getBlockRotationMatrix()[0];
120                                        //m1.print(3,3);
121                                        Atom   vector1 = afpChain.getBlockShiftVector()[0];
122                                        //System.out.println("shift vector:" + vector1);
123
124                                        for ( Group g : hetatms2){
125                                                Calc.rotate(g, m1);
126                                                Calc.shift(g,vector1);
127                                        }
128                                }
129                        }
130                }
131
132                return twistedGroups;
133        }
134
135        /** only shift CA positions.
136        *
137        */
138        public static void shiftCA2(AFPChain afpChain, Atom[] ca2,  Matrix m, Atom shift, Group[] twistedGroups) {
139
140                int i = -1;
141                for (Atom a: ca2){
142                        i++;
143                        Group g = a.getGroup();
144
145                        Calc.rotate(g,m);
146                        Calc.shift(g, shift);
147
148                        if (g.hasAltLoc()){
149                         for (Group alt: g.getAltLocs()){
150                                 for (Atom alta : alt.getAtoms()){
151                                         if ( g.getAtoms().contains(alta))
152                                                 continue;
153                                         Calc.rotate(alta,m);
154                                         Calc.shift(alta,shift);
155                                 }
156                         }
157                        }
158                        twistedGroups[i]=g;
159                }
160        }
161
162}