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/**
044 * A class that does calculations on an AFPChain
045 *
046 * @author Andreas Prlic
047 *
048 */
049public class FatCatAligner
050{
051
052        public static final boolean debug = false;
053        public static final boolean printTimeStamps = false;
054
055        AFPChain afpChain ;
056        Group[] twistedGroups;
057
058
059
060        public AFPChain getAfpChain()
061        {
062                return afpChain;
063        }
064
065
066        public Group[] getTwistedGroups()
067        {
068
069                return twistedGroups;
070        }
071
072        public void setTwistedGroups(Group[] twistedGroups)
073        {
074                this.twistedGroups = twistedGroups;
075        }
076
077
078        public  void align(Atom[] ca1, Atom[] ca2, boolean doRigid, FatCatParameters params) throws StructureException{
079
080                long tstart = System.currentTimeMillis();
081
082                afpChain = new AFPChain(FatCat.algorithmName);
083                afpChain.setCa1Length(ca1.length);
084                afpChain.setCa2Length(ca2.length);
085
086
087
088                AFPCalculator.extractAFPChains(params, afpChain,ca1, ca2);
089
090                long cend = System.currentTimeMillis();
091
092                if (printTimeStamps)
093                        System.out.println("calculation took:" + (cend - tstart) + " ms.");
094
095
096                AFPCalculator.sortAfps(afpChain,ca1,ca2);
097
098                if ( printTimeStamps) {
099                        long send = System.currentTimeMillis();
100
101
102                        System.out.println("sorting  took:" + (send - cend) + " ms.");
103                }
104
105                if ( doRigid)
106                        this.twistedGroups = rChainAfp(params, afpChain,ca1,ca2);
107
108                else {
109                        this.twistedGroups = chainAfp(params,afpChain,ca1,ca2);
110                }
111
112                // long start = System.currentTimeMillis();
113                long end = System.currentTimeMillis();
114                afpChain.setCalculationTime(end-tstart);
115                if ( printTimeStamps)
116                        System.out.println("TOTAL calc time: " + (end -tstart) / 1000.0);
117
118        }
119
120
121
122
123        /** runs rigid chaining process
124         *
125         */
126        private static Group[] rChainAfp(FatCatParameters params, AFPChain afpChain, Atom[] ca1, Atom[] ca2) throws StructureException{
127                params.setMaxTra(0);
128                afpChain.setMaxTra(0);
129                return chainAfp(params,afpChain,ca1,ca2);
130        }
131
132        /**
133         * run AFP chaining allowing up to maxTra flexible regions.
134         * Input is original coordinates.
135         *
136         */
137        private static Group[] chainAfp(FatCatParameters params,AFPChain afpChain, Atom[] ca1, Atom[] ca2) throws StructureException{
138
139                // we don;t want to rotate input atoms, do we?
140                Atom[] ca2clone = StructureTools.cloneAtomArray(ca2);
141
142                List<AFP> afpSet = afpChain.getAfpSet();
143
144                if (debug)
145                        System.out.println("entering chainAfp");
146                int afpNum = afpSet.size();
147
148                if ( afpNum < 1)
149                        return new Group[0];
150
151                long bgtime = System.currentTimeMillis();
152                if(debug)    {
153                        System.out.println(String.format("total AFP %d\n", afpNum));
154                }
155
156                //run AFP chaining
157
158                AFPChainer.doChainAfp(params,afpChain ,ca1,ca2);
159
160                int afpChainLen = afpChain.getAfpChainLen();
161
162                if(afpChainLen < 1)     {
163
164                        afpChain.setShortAlign(true);
165                        return new Group[0];
166                } //very short alignment
167
168                long chaintime = System.currentTimeMillis();
169                if(debug)    {
170
171                        System.out.println("Afp chaining: time " + (chaintime-bgtime));
172                }
173
174                // do post processing
175
176                AFPPostProcessor.postProcess(params, afpChain,ca1,ca2);
177
178                // Optimize the final alignment
179
180                AFPOptimizer.optimizeAln(params, afpChain,ca1,ca2);
181
182                AFPOptimizer.blockInfo( afpChain);
183
184                AFPOptimizer.updateScore(params,afpChain);
185
186                AFPAlignmentDisplay.getAlign(afpChain,ca1,ca2);
187
188                Group[] twistedPDB = AFPTwister.twistPDB(afpChain, ca1, ca2clone);
189
190                SigEva sig =  new SigEva();
191                double probability = sig.calSigAll(params, afpChain);
192                afpChain.setProbability(probability);
193                double normAlignScore = sig.calNS(params,afpChain);
194                afpChain.setNormAlignScore(normAlignScore);
195                double tmScore = AFPChainScorer.getTMScore(afpChain, ca1, ca2,false);
196                afpChain.setTMScore(tmScore);
197
198                /*
199
200                SIGEVA  sig;
201                probability = sig.calSigAll(maxTra, sparse, pro1Len, pro2Len, alignScore, totalRmsdOpt, optLength, blockNum - 1);
202                normAlignScore = sig.calNS(pro1Len, pro2Len, alignScore, totalRmsdOpt, optLength, blockNum - 1);
203
204                 */
205
206                //if(maxTra == 0)       probability = sig.calSigRigid(pro1Len, pro2Len, alignScore, totalRmsdOpt, optLength);
207                //else  probability = sig.calSigFlexi(pro1Len, pro2Len, alignScore, totalRmsdOpt, optLength, blockNum - 1);
208
209                if(debug)    {
210
211                        long nowtime = System.currentTimeMillis();
212                        long diff = nowtime - chaintime;
213                        System.out.println("Alignment optimization: time "+ diff);
214
215                        System.out.println("score:      " + afpChain.getAlignScore());
216                        System.out.println("opt length: " + afpChain.getOptLength());
217                        System.out.println("opt rmsd:   "+ afpChain.getTotalRmsdOpt());
218
219                }
220                return twistedPDB;
221
222        }
223
224}