001/* This class is based on the original FATCAT implementation by
002 * <pre>
003 * Yuzhen Ye & Adam Godzik (2003)
004 * Flexible structure alignment by chaining aligned fragment pairs allowing twists.
005 * Bioinformatics vol.19 suppl. 2. ii246-ii255.
006 * https://www.ncbi.nlm.nih.gov/pubmed/14534198
007 * </pre>
008 *
009 * Thanks to Yuzhen Ye and A. Godzik for granting permission to freely use and redistribute this code.
010 *
011 * This code may be freely distributed and modified under the
012 * terms of the GNU Lesser General Public Licence.  This should
013 * be distributed with the code.  If you do not have a copy,
014 * see:
015 *
016 *      http://www.gnu.org/copyleft/lesser.html
017 *
018 * Copyright for this code is held jointly by the individual
019 * authors.  These should be listed in @author doc comments.
020 *
021 *
022 * Created on Jun 17, 2009
023 * Created by Andreas Prlic - RCSB PDB
024 *
025 */
026
027package org.biojava.nbio.structure.align.fatcat.calc;
028
029import org.biojava.nbio.structure.Atom;
030import org.biojava.nbio.structure.Group;
031import org.biojava.nbio.structure.StructureException;
032import org.biojava.nbio.structure.StructureTools;
033import org.biojava.nbio.structure.align.AFPTwister;
034import org.biojava.nbio.structure.align.fatcat.FatCat;
035import org.biojava.nbio.structure.align.model.AFP;
036import org.biojava.nbio.structure.align.model.AFPChain;
037import org.biojava.nbio.structure.align.util.AFPAlignmentDisplay;
038import org.biojava.nbio.structure.align.util.AFPChainScorer;
039
040import java.util.List;
041
042
043/** A class that does calculations on an AFPChain
044 *
045 * @author Andreas Prlic
046 *
047 */
048public class FatCatAligner
049{
050
051        public static final boolean debug = false;
052        public static final boolean printTimeStamps = false;
053
054        AFPChain afpChain ;
055        Group[] twistedGroups;
056
057
058
059        public AFPChain getAfpChain()
060        {
061                return afpChain;
062        }
063
064
065        public Group[] getTwistedGroups()
066        {
067
068                return twistedGroups;
069        }
070
071        public void setTwistedGroups(Group[] twistedGroups)
072        {
073                this.twistedGroups = twistedGroups;
074        }
075
076
077        public  void align(Atom[] ca1, Atom[] ca2, boolean doRigid, FatCatParameters params) throws StructureException{
078
079                long tstart = System.currentTimeMillis();
080
081                afpChain = new AFPChain(FatCat.algorithmName);
082                afpChain.setCa1Length(ca1.length);
083                afpChain.setCa2Length(ca2.length);
084
085
086
087                AFPCalculator.extractAFPChains(params, afpChain,ca1, ca2);
088
089                long cend = System.currentTimeMillis();
090
091                if (printTimeStamps)
092                        System.out.println("calculation took:" + (cend - tstart) + " ms.");
093
094
095                AFPCalculator.sortAfps(afpChain,ca1,ca2);
096
097                if ( printTimeStamps) {
098                        long send = System.currentTimeMillis();
099
100
101                        System.out.println("sorting  took:" + (send - cend) + " ms.");
102                }
103
104                if ( doRigid)
105                        this.twistedGroups = rChainAfp(params, afpChain,ca1,ca2);
106
107                else {
108                        this.twistedGroups = chainAfp(params,afpChain,ca1,ca2);
109                }
110
111                // long start = System.currentTimeMillis();
112                long end = System.currentTimeMillis();
113                afpChain.setCalculationTime(end-tstart);
114                if ( printTimeStamps)
115                        System.out.println("TOTAL calc time: " + (end -tstart) / 1000.0);
116
117        }
118
119
120
121
122        /** runs rigid chaining process
123         *
124         */
125        private static Group[] rChainAfp(FatCatParameters params, AFPChain afpChain, Atom[] ca1, Atom[] ca2) throws StructureException{
126                params.setMaxTra(0);
127                afpChain.setMaxTra(0);
128                return chainAfp(params,afpChain,ca1,ca2);
129        }
130
131        /**
132         * run AFP chaining allowing up to maxTra flexible regions.
133         * Input is original coordinates.
134         *
135         */
136        private static Group[] chainAfp(FatCatParameters params,AFPChain afpChain, Atom[] ca1, Atom[] ca2) throws StructureException{
137
138                // we don;t want to rotate input atoms, do we?
139                Atom[] ca2clone = StructureTools.cloneAtomArray(ca2);
140
141                List<AFP> afpSet = afpChain.getAfpSet();
142
143                if (debug)
144                        System.out.println("entering chainAfp");
145                int afpNum = afpSet.size();
146
147                if ( afpNum < 1)
148                        return new Group[0];
149
150                long bgtime = System.currentTimeMillis();
151                if(debug)    {
152                        System.out.println(String.format("total AFP %d\n", afpNum));
153                }
154
155                //run AFP chaining
156
157                AFPChainer.doChainAfp(params,afpChain ,ca1,ca2);
158
159                int afpChainLen = afpChain.getAfpChainLen();
160
161                if(afpChainLen < 1)     {
162
163                        afpChain.setShortAlign(true);
164                        return new Group[0];
165                } //very short alignment
166
167                long chaintime = System.currentTimeMillis();
168                if(debug)    {
169
170                        System.out.println("Afp chaining: time " + (chaintime-bgtime));
171                }
172
173                // do post processing
174
175                AFPPostProcessor.postProcess(params, afpChain,ca1,ca2);
176
177                // Optimize the final alignment
178
179                AFPOptimizer.optimizeAln(params, afpChain,ca1,ca2);
180
181                AFPOptimizer.blockInfo( afpChain);
182
183                AFPOptimizer.updateScore(params,afpChain);
184
185                AFPAlignmentDisplay.getAlign(afpChain,ca1,ca2);
186
187                Group[] twistedPDB = AFPTwister.twistPDB(afpChain, ca1, ca2clone);
188
189                SigEva sig =  new SigEva();
190                double probability = sig.calSigAll(params, afpChain);
191                afpChain.setProbability(probability);
192                double normAlignScore = sig.calNS(params,afpChain);
193                afpChain.setNormAlignScore(normAlignScore);
194                double tmScore = AFPChainScorer.getTMScore(afpChain, ca1, ca2,false);
195                afpChain.setTMScore(tmScore);
196
197                /*
198
199                SIGEVA  sig;
200                probability = sig.calSigAll(maxTra, sparse, pro1Len, pro2Len, alignScore, totalRmsdOpt, optLength, blockNum - 1);
201                normAlignScore = sig.calNS(pro1Len, pro2Len, alignScore, totalRmsdOpt, optLength, blockNum - 1);
202
203                 */
204
205                //if(maxTra == 0)       probability = sig.calSigRigid(pro1Len, pro2Len, alignScore, totalRmsdOpt, optLength);
206                //else  probability = sig.calSigFlexi(pro1Len, pro2Len, alignScore, totalRmsdOpt, optLength, blockNum - 1);
207
208                if(debug)    {
209
210                        long nowtime = System.currentTimeMillis();
211                        long diff = nowtime - chaintime;
212                        System.out.println("Alignment optimization: time "+ diff);
213
214                        System.out.println("score:      " + afpChain.getAlignScore());
215                        System.out.println("opt length: " + afpChain.getOptLength());
216                        System.out.println("opt rmsd:   "+ afpChain.getTotalRmsdOpt());
217
218                }
219                return twistedPDB;
220
221        }
222
223}