001/*
002 *                    PDB web 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 *
015 * Created on Jun 17, 2009
016 * Created by ap3
017 *
018 */
019package org.biojava.nbio.structure.align.model;
020
021import org.biojava.nbio.structure.Atom;
022import org.biojava.nbio.structure.align.ce.CeMain;
023import org.biojava.nbio.structure.align.ce.CeSideChainMain;
024import org.biojava.nbio.structure.align.util.AFPAlignmentDisplay;
025import org.biojava.nbio.structure.jama.Matrix;
026
027import java.io.Serializable;
028import java.util.ArrayList;
029import java.util.Arrays;
030import java.util.List;
031import java.util.Map;
032
033/**
034 * A bean to contain the core of a structure alignment.
035 * The FatCat aligner class is working on the AFPChain class.
036 *
037 * @author Andreas Prlic
038 * @author Aleix Lafita
039 *
040 */
041public class AFPChain implements Serializable, Cloneable {
042
043        private static final long serialVersionUID = -4474029015606617947L;
044        public static final String newline = System.getProperty("line.separator");
045        public static final String UNKNOWN_ALGORITHM = "unknown";
046
047        private String algorithmName;
048        private String version;
049
050        private String name1;
051        private String name2;
052        private long ioTime;
053        private long calculationTime;
054        private long id;
055
056        // results:
057        private double alignScore;
058        private double alignScoreUpdate;
059        private int afpChainTwiNum;
060
061        // end of results
062        private double tmScore;
063
064        // utility
065        private int minLen ; // the length of the shorter 2 proteins.
066
067
068        private List<AFP> afpSet;
069        private int[][] afpIndex;
070        private int[][] afpAftIndex;
071        private int[][] afpBefIndex;
072
073        private Matrix disTable1;
074        private Matrix disTable2;
075
076        private int[] twi = null ; //the number of twists making the best score ending at each AFP
077
078        private int afpChainLen;
079        private int[] afpChainList;
080        private double[] afpChainTwiBin;
081        private double[] afpChainTwiList;
082        private double chainRmsd;
083
084        private int chainLen,misLen,gapLen;
085        private int     blockNum;       //the final block number
086        private int     blockNumIni;    //block number before block clustering and split
087        private int     blockNumClu;    //block number after clustering blocks
088        private int     blockNumSpt;    //block number after spliting blocks
089        private double[]  blockRmsd;     //the RMSD of each block
090        private int[]     block2Afp;     //the index of afp for each block
091        private int[]     blockSize;     //the number of AFPs involved in a block
092        private double[]  blockScore;    //the score associated with each block
093        private int[]     blockGap;      //the gaps in each block
094        private int[]     blockResSize;  //the number of residues involved in a block
095        private int[][][]     blockResList;//the list of AFP for each block
096        private Matrix[] blockRotationMatrix;
097        private Atom[]   blockShiftVector;
098
099        private int     focusResn;      //the size of the set
100        private int[]     focusRes1;     //the residues from protein 1
101        private int[]     focusRes2;     //the residues from protein 2
102        private int     focusAfpn;      //the AFP number
103        private int[]     focusAfpList;  //the AFP list
104
105        private boolean shortAlign;
106
107        private String [][][] pdbAln; // only needed temp. during XML serialization, since we don;t have coordinates loaded at that time and can map from PDB res numbers to atom positions.
108        private int[][][] optAln;
109        private int[] optLen ;
110        private double[] optRmsd ;
111        private int optLength;
112
113        private char[] alnsymb;
114        private char[] alnseq1;
115        private char[] alnseq2;
116        private int alnLength;
117        private int alnbeg1;
118        private int alnbeg2;
119
120        private int totalLenIni;
121        private int totalLenOpt = 0;
122
123        private double totalRmsdIni;
124        private double totalRmsdOpt;
125
126        private int ca1Length;
127        private int ca2Length;
128
129        // this one is special. it comes from the FatCatParameters...
130        // default is flexible alignment...
131        private int maxTra = 5;
132
133        private Double conn;
134        private Double dvar;
135
136        private double probability;
137        private double identity;
138        private double similarity;
139        private double normAlignScore;
140
141        private int myResultsEQR;
142        private int myResultsSimilarity1;
143        private int myResultsSimilarity2;
144
145        // Mark whether the alignment topology is sequential
146        // false if a circular permutation has occured
147        private boolean sequentialAlignment;
148
149        // background distances
150        private Matrix distanceMatrix;
151
152        private String description2;
153
154        /**
155         * Construction of an AFPChain needs the algorithm name, since downstream
156         * analysis methods (scores, display, etc) behave differently if the
157         * alignment is flexible (created with FatCat).
158         *
159         * @param algorithmName
160         */
161        public AFPChain(String algorithmName){
162                this.algorithmName = algorithmName;
163                init();
164        }
165
166        /**
167         * Copy constructor
168         * @param o AFPChain to duplicate
169         */
170        public AFPChain(AFPChain o) {
171                this.algorithmName = o.algorithmName;
172                this.version = o.version;
173                this.name1 = o.name1;
174                this.name2 = o.name2;
175                this.ioTime = o.ioTime;
176                this.calculationTime = o.calculationTime;
177                this.id = o.id;
178                this.alignScore = o.alignScore;
179                this.alignScoreUpdate = o.alignScoreUpdate;
180                this.afpChainTwiNum = o.afpChainTwiNum;
181                this.minLen = o.minLen;
182                this.afpSet = new ArrayList<AFP>(o.afpSet);
183                this.afpIndex = o.afpIndex == null? null: o.afpIndex.clone();
184                this.afpAftIndex = o.afpAftIndex == null? null: o.afpAftIndex.clone();
185                this.afpBefIndex = o.afpBefIndex == null? null: o.afpBefIndex.clone();
186                this.disTable1 = o.disTable1 == null? null: (Matrix) o.disTable1.clone();
187                this.disTable2 = o.disTable2 == null? null: (Matrix) o.disTable2.clone();
188                this.twi = o.twi == null ? null : o.twi.clone();
189                this.afpChainLen = o.afpChainLen;
190                this.afpChainList = o.afpChainList == null? null: o.afpChainList.clone();
191                this.afpChainTwiBin = o.afpChainTwiBin == null? null: o.afpChainTwiBin.clone();
192                this.afpChainTwiList = o.afpChainTwiList == null? null: o.afpChainTwiList.clone();
193                this.chainRmsd = o.chainRmsd;
194                this.chainLen = o.chainLen;
195                this.misLen = o.misLen;
196                this.gapLen = o.gapLen;
197                this.blockNum = o.blockNum;
198                this.blockNumIni = o.blockNumIni;
199                this.blockNumClu = o.blockNumClu;
200                this.blockNumSpt = o.blockNumSpt;
201                this.blockRmsd = o.blockRmsd == null ? null : o.blockRmsd.clone();
202                this.block2Afp = o.block2Afp == null ? null : o.block2Afp.clone();
203                this.blockSize = o.blockSize == null ? null : o.blockSize.clone();
204                this.blockScore = o.blockScore == null ? null : o.blockScore.clone();
205                this.blockGap = o.blockGap == null ? null : o.blockGap.clone();
206                this.blockResSize = o.blockResSize == null ? null : o.blockResSize.clone();
207                this.blockResList = o.blockResList == null ? null : o.blockResList.clone();
208                this.blockRotationMatrix = o.blockRotationMatrix == null ? null : o.blockRotationMatrix.clone();
209                this.blockShiftVector = o.blockShiftVector == null ? null : o.blockShiftVector.clone();
210                this.focusResn = o.focusResn;
211                this.focusRes1 = o.focusRes1 == null ? null : o.focusRes1.clone();
212                this.focusRes2 = o.focusRes2 == null ? null : o.focusRes2.clone();
213                this.focusAfpn = o.focusAfpn;
214                this.focusAfpList = o.focusAfpList == null ? null : o.focusAfpList.clone();
215                this.shortAlign = o.shortAlign;
216                this.pdbAln = o.pdbAln == null ? null : o.pdbAln.clone();
217                this.optAln = o.optAln == null ? null : o.optAln.clone();
218                this.optLen = o.optLen == null ? null : o.optLen.clone();
219                this.optRmsd = o.optRmsd == null ? null : o.optRmsd.clone();
220                this.optLength = o.optLength;
221                this.alnsymb = o.alnsymb == null ? null : o.alnsymb.clone();
222                this.alnseq1 = o.alnseq1 == null ? null : o.alnseq1.clone();
223                this.alnseq2 = o.alnseq2 == null ? null : o.alnseq2.clone();
224                this.alnLength = o.alnLength;
225                this.alnbeg1 = o.alnbeg1;
226                this.alnbeg2 = o.alnbeg2;
227                this.totalLenIni = o.totalLenIni;
228                this.totalLenOpt = o.totalLenOpt;
229                this.totalRmsdIni = o.totalRmsdIni;
230                this.totalRmsdOpt = o.totalRmsdOpt;
231                this.ca1Length = o.ca1Length;
232                this.ca2Length = o.ca2Length;
233                this.maxTra = o.maxTra;
234                this.conn = new Double(o.conn);
235                this.dvar = new Double(o.dvar);
236                this.probability = o.probability;
237                this.identity = o.identity;
238                this.similarity = o.similarity;
239                this.normAlignScore = o.normAlignScore;
240                this.myResultsEQR = o.myResultsEQR;
241                this.myResultsSimilarity1 = o.myResultsSimilarity1;
242                this.myResultsSimilarity2 = o.myResultsSimilarity2;
243                this.distanceMatrix = o.distanceMatrix;
244        }
245
246        /**
247         * Creates and returns a copy of this object.
248         */
249        @Override
250        public Object clone() {
251                return new AFPChain(this);
252        }
253
254        public long getId()
255        {
256                return id;
257        }
258        public void setId(long id)
259        {
260                this.id = id;
261        }
262
263        public String toCE(Atom[] ca1, Atom[]ca2) {
264
265                return AfpChainWriter.toCE(this,ca1,ca2);
266
267        }
268
269        public String toRotMat(){
270
271                return AfpChainWriter.toRotMat(this);
272        }
273
274        public String toFatcat(Atom[] ca1, Atom[]ca2){
275
276                return AfpChainWriter.toFatCat(this,ca1,ca2);
277
278        }
279
280        public String toDBSearchResult(){
281
282                return AfpChainWriter.toDBSearchResult(this);
283        }
284
285        protected void calcSimilarity() {
286                Map<String,Double> idMap = AFPAlignmentDisplay.calcIdSimilarity(alnseq1,alnseq2,alnLength);
287
288                //probability = idMap.get("probability");
289                similarity = idMap.get("similarity");
290                identity   = idMap.get("identity");
291
292        }
293
294
295
296
297        /**
298         * Get the number of structurally equivalent residues
299         *
300         * @return nr of EQR
301         */
302        public int getNrEQR(){
303
304                if (myResultsEQR < 0){
305                        if ( optLen == null) {
306                                myResultsEQR = 0;
307                                return 0;
308                        }
309
310                        int nrEqr = 0;
311                        for(int bk = 0; bk < blockNum; bk ++)       {
312
313                                for ( int i=0;i< optLen[bk];i++){
314                                        nrEqr++;
315                                }
316                        }
317                        myResultsEQR = nrEqr;
318                }
319                return myResultsEQR;
320        }
321
322        /** Get the coverage of protein 1 with the alignment
323         *
324         * @return percentage of coverage, between 0 and 100.
325         */
326        public int getCoverage1(){
327                if ( myResultsSimilarity1 < 0 ) {
328                        int distance = ca1Length + ca2Length - 2 * getNrEQR();
329
330                        int similarity = (ca1Length + ca2Length - distance ) / 2;
331
332                        myResultsSimilarity1 = Math.round(similarity /(float) ca1Length * 100);
333                }
334                return myResultsSimilarity1;
335        }
336
337        /** Get the coverage of protein 2 with the alignment
338         *
339         * @return percentage of coverage, between 0 and 100.
340         */
341        public int getCoverage2(){
342                if ( myResultsSimilarity2 < 0 ) {
343
344
345                        int distance = ca1Length + ca2Length - 2 * getNrEQR();
346
347                        int similarity = (ca1Length + ca2Length - distance ) / 2;
348                        myResultsSimilarity2 = Math.round(similarity /(float) ca2Length * 100);
349                }
350                return myResultsSimilarity2;
351
352        }
353
354        @Override
355        public String toString(){
356
357                //int lA = ca1Length;
358                //int lB = ca2Length;
359                //int distance = lA + lB - 2 * getNrEQR();
360
361                StringBuffer str = new StringBuffer("");
362                str.append("EQR:");
363                str.append(getNrEQR());
364
365                str.append("\tLen1:");
366                str.append(this.getCa1Length());
367                str.append("\tLen2:");
368                str.append(this.getCa2Length());
369                str.append(String.format("\tscore: %.2f",this.getAlignScore()));
370                str.append("\t");
371                if ( algorithmName.equalsIgnoreCase(CeMain.algorithmName) || algorithmName.equalsIgnoreCase(CeSideChainMain.algorithmName)){
372                        str.append("Z-score:");
373                        str.append(String.format("%.2f",this.getProbability()));
374                } else {
375                        str.append("Probability:");
376                        str.append(String.format("%.2e",this.getProbability()));
377                }
378                str.append("\tRMSD:");
379                str.append(String.format("%.2f",this.getTotalRmsdOpt()));
380
381                str.append("\tSeqID:");
382                str.append(String.format("%.0f",getIdentity()*100));
383                str.append("%\tSeqSim:");
384                str.append(String.format("%.0f",getSimilarity()*100));
385                str.append("%\tCov1:");
386                str.append(this.getCoverage1());
387                str.append("%\tCov2:");
388                str.append(this.getCoverage2());
389                str.append("%");
390
391                if (  tmScore != -1)  {
392                        str.append("\ttmScore:");
393                        str.append(String.format("%.2f",tmScore));
394                }
395                str.append(newline);
396
397
398                return str.toString();
399        }
400
401        public boolean isSignificantResult(){
402                if ( algorithmName.equalsIgnoreCase(CeMain.algorithmName) || algorithmName.equalsIgnoreCase(CeSideChainMain.algorithmName)){
403                        if (probability >= 3.5)
404                                return true;
405                } else {
406                        if (probability < 0.01)
407                                return true;
408                }
409                return false;
410        }
411
412
413
414
415        private void init(){
416                shortAlign = false;
417                afpChainLen = 0;
418
419                afpChainList      = null;
420                afpChainTwiBin  = null;
421                afpChainTwiList = null;
422                chainRmsd=0;
423                chainLen = misLen = gapLen = 0;
424
425                blockResSize = null;
426                blockScore = null;
427                blockGap = null;
428                optAln = null;
429                pdbAln = null;
430                optLen = null;
431
432                optRmsd = null;
433
434                block2Afp = new int[maxTra+1];
435                blockSize = new int[maxTra+1];
436                blockRmsd = new double[maxTra+1];
437                blockScore = new double[maxTra+1];
438                blockGap = new int[maxTra+1];
439
440                blockResSize = new int[maxTra+1];
441
442                afpSet = new ArrayList<AFP>();
443                totalLenIni = totalLenOpt = 0;
444                totalRmsdIni = totalRmsdOpt = 0.0;
445
446                afpChainTwiNum = 0;
447                alignScore = 0;
448                alignScoreUpdate = 0;
449                conn = new Double(0);
450                dvar = new Double(0);
451                calculationTime = 0;
452
453                similarity = -1;
454                identity   = -1;
455                myResultsEQR = -1;
456                myResultsSimilarity1 = -1;
457                myResultsSimilarity2 = -1;
458                version = "1.0";
459                sequentialAlignment = true;
460                distanceMatrix = null;
461                tmScore = -1;
462                description2=null;
463        }
464
465        /**
466         * Resets properties which can be calculated on the fly
467         */
468        private void invalidate() {
469                myResultsEQR = -1;
470                myResultsSimilarity1 = -1;
471                myResultsSimilarity2 = -1;
472                identity = -1;
473                similarity = -1;
474        }
475
476        /** used temporarily during XML serialization to track the PDB positions of the alignmnet
477         *
478         * @return String array
479         */
480        public String[][][] getPdbAln() {
481                return pdbAln;
482        }
483
484
485        public void setPdbAln(String[][][] pdbAln) {
486                this.pdbAln = pdbAln;
487        }
488
489
490        public Double getConn()
491        {
492                return conn;
493        }
494
495
496        public void setConn(Double conn)
497        {
498                this.conn = conn;
499        }
500
501
502        public Double getDVar()
503        {
504                return dvar;
505        }
506
507
508        public void setDVar(Double dvar)
509        {
510                this.dvar = dvar;
511        }
512
513
514        /** get the maximum nr of Twists that are allowed...
515         *
516         * @return maxTra, the max nr of twists
517         */
518        public int getMaxTra()
519        {
520                return maxTra;
521        }
522
523        /**
524         * Set the maximum number of Twists that are allowed...
525         * @param maxTra
526         */
527        public void setMaxTra(int maxTra)
528        {
529                this.maxTra = maxTra;
530        }
531
532
533        public double getAlignScore()
534        {
535                return alignScore;
536        }
537
538        public void setAlignScore(double alignScore)
539        {
540                this.alignScore = alignScore;
541        }
542
543        public double getAlignScoreUpdate()
544        {
545                return alignScoreUpdate;
546        }
547
548        public void setAlignScoreUpdate(double alignScoreUpdate)
549        {
550                this.alignScoreUpdate = alignScoreUpdate;
551        }
552
553        public int getAfpChainTwiNum()
554        {
555                return afpChainTwiNum;
556        }
557
558        public void setAfpChainTwiNum(int afpChainTwiNum)
559        {
560                this.afpChainTwiNum = afpChainTwiNum;
561        }
562
563        public int getMinLen()
564        {
565                return minLen;
566        }
567
568        public void setMinLen(int minLen)
569        {
570                this.minLen = minLen;
571        }
572
573
574
575        /**
576         * Get the set of AFPs for this alignment.
577         * An AFP is a local ungapped alignment between the two peptides.
578         *
579         * AFPs are set before the final optimization step. To get the final
580         * alignment, look at the aligned pairs from {@link #getOptAln()}.
581         *
582         * @return The optimal set of AFPs
583         * @see #getOptAln()
584         */
585        public List<AFP> getAfpSet()
586        {
587                return afpSet;
588        }
589
590
591        /**
592         * Set the set of AFPs for this alignment.
593         * An AFP is a local ungapped alignment between the two peptides.
594         *
595         * AFPs are set before the final optimization step. To get the final
596         * alignment, look at the aligned pairs from {@link #getOptAln()}.
597         */
598        public void setAfpSet(List<AFP> afpSet)
599        {
600                this.afpSet = afpSet;
601        }
602
603        public int[][] getAfpIndex()
604        {
605                return afpIndex;
606        }
607
608        public void setAfpIndex(int[][] afpIndex)
609        {
610                this.afpIndex = afpIndex;
611        }
612
613
614        public int[][] getAfpAftIndex()
615        {
616                return afpAftIndex;
617        }
618
619        public void setAfpAftIndex(int[][] afpAftIndex)
620        {
621                this.afpAftIndex = afpAftIndex;
622        }
623
624
625        public int[][] getAfpBefIndex()
626        {
627                return afpBefIndex;
628        }
629
630        public void setAfpBefIndex(int[][] afpBefIndex)
631        {
632                this.afpBefIndex = afpBefIndex;
633        }
634
635
636        public Matrix getDisTable1()
637        {
638                return disTable1;
639        }
640
641        public void setDisTable1(Matrix disTable1)
642        {
643                this.disTable1 = disTable1;
644        }
645
646
647        public Matrix getDisTable2()
648        {
649                return disTable2;
650        }
651
652        public void setDisTable2(Matrix disTable2)
653        {
654                this.disTable2 = disTable2;
655        }
656
657
658        public int[] getTwi()
659        {
660                return twi;
661        }
662
663        public void setTwi(int[] twi)
664        {
665                this.twi = twi;
666        }
667
668        public int getAfpChainLen()
669        {
670                return afpChainLen;
671        }
672
673        public void setAfpChainLen(int afpChainLen)
674        {
675                this.afpChainLen = afpChainLen;
676        }
677
678        public int[] getAfpChainList()
679        {
680                return afpChainList;
681        }
682
683        public void setAfpChainList(int[] afpChainList)
684        {
685                this.afpChainList = afpChainList;
686        }
687
688        public double[] getAfpChainTwiBin()
689        {
690                return afpChainTwiBin;
691        }
692
693        public void setAfpChainTwiBin(double[] afpChainTwiBin)
694        {
695                this.afpChainTwiBin = afpChainTwiBin;
696        }
697
698        public double[] getAfpChainTwiList()
699        {
700                return afpChainTwiList;
701        }
702
703        public void setAfpChainTwiList(double[] afpChainTwiList)
704        {
705                this.afpChainTwiList = afpChainTwiList;
706        }
707
708        public double getChainRmsd()
709        {
710                return chainRmsd;
711        }
712
713        /** The RMSD of the chain of AFPs. Set during AFPCHainer.traceBack();
714         *
715         * @param chainRmsd
716         */
717        public void setChainRmsd(double chainRmsd)
718        {
719                this.chainRmsd = chainRmsd;
720        }
721
722        public int getChainLen()
723        {
724                return chainLen;
725        }
726
727        public void setChainLen(int chainLen)
728        {
729                this.chainLen = chainLen;
730        }
731
732        public int getMisLen()
733        {
734                return misLen;
735        }
736
737        public void setMisLen(int misLen)
738        {
739                this.misLen = misLen;
740        }
741
742        public int getGapLen()
743        {
744                return gapLen;
745        }
746
747        public void setGapLen(int gapLen)
748        {
749                this.gapLen = gapLen;
750        }
751
752        /** The number of blocks in the alignment
753         *
754         * @return the nr of blocks in alignment
755         */
756        public int getBlockNum()
757        {
758                return blockNum;
759        }
760
761        public void setBlockNum(int blockNum)
762        {
763                this.blockNum = blockNum;
764        }
765
766        public int getBlockNumIni()
767        {
768                return blockNumIni;
769        }
770
771        public void setBlockNumIni(int blockNumIni)
772        {
773                this.blockNumIni = blockNumIni;
774        }
775
776        public int getBlockNumClu()
777        {
778                return blockNumClu;
779        }
780
781        public void setBlockNumClu(int blockNumClu)
782        {
783                this.blockNumClu = blockNumClu;
784        }
785
786        public int getBlockNumSpt()
787        {
788                return blockNumSpt;
789        }
790
791        public void setBlockNumSpt(int blockNumSpt)
792        {
793                this.blockNumSpt = blockNumSpt;
794        }
795
796        public double[] getBlockRmsd()
797        {
798                return blockRmsd;
799        }
800
801        public void setBlockRmsd(double[] blockRmsd)
802        {
803                this.blockRmsd = blockRmsd;
804        }
805
806        public int[] getBlock2Afp()
807        {
808                return block2Afp;
809        }
810
811        public void setBlock2Afp(int[] block2Afp)
812        {
813                this.block2Afp = block2Afp;
814        }
815
816        public int[] getBlockSize()
817        {
818                return blockSize;
819        }
820
821        public void setBlockSize(int[] blockSize)
822        {
823                this.blockSize = blockSize;
824        }
825
826        public double[] getBlockScore()
827        {
828                return blockScore;
829        }
830
831        public void setBlockScore(double[] blockScore)
832        {
833                this.blockScore = blockScore;
834        }
835
836        public int[] getBlockGap()
837        {
838                return blockGap;
839        }
840
841        public void setBlockGap(int[] blockGap)
842        {
843                this.blockGap = blockGap;
844        }
845
846        public int[] getBlockResSize()
847        {
848                return blockResSize;
849        }
850
851        public void setBlockResSize(int[] blockResSize)
852        {
853                this.blockResSize = blockResSize;
854        }
855
856
857        /** tracks the residues of the initial blocks (before optimization)
858         *
859         *
860         * @return list of block residues
861         */
862        public int[][][] getBlockResList()
863        {
864                return blockResList;
865        }
866
867        public void setBlockResList(int[][][] blockResList)
868        {
869                this.blockResList = blockResList;
870        }
871
872        public int getFocusResn()
873        {
874                return focusResn;
875        }
876
877        public void setFocusResn(int focusResn)
878        {
879                this.focusResn = focusResn;
880        }
881
882
883        public int[] getFocusRes1()
884        {
885                return focusRes1;
886        }
887
888        public void setFocusRes1(int[] focusRes1)
889        {
890                this.focusRes1 = focusRes1;
891        }
892
893
894        public int[] getFocusRes2()
895        {
896                return focusRes2;
897        }
898
899        public void setFocusRes2(int[] focusRes2)
900        {
901                this.focusRes2 = focusRes2;
902        }
903
904        public int getFocusAfpn()
905        {
906                return focusAfpn;
907        }
908
909        public void setFocusAfpn(int focusAfpn)
910        {
911                this.focusAfpn = focusAfpn;
912        }
913
914        public int[] getFocusAfpList()
915        {
916                return focusAfpList;
917        }
918
919        public void setFocusAfpList(int[] focusAfpList)
920        {
921                this.focusAfpList = focusAfpList;
922        }
923
924        public boolean isShortAlign()
925        {
926                return shortAlign;
927        }
928
929        public void setShortAlign(boolean shortAlign)
930        {
931                this.shortAlign = shortAlign;
932        }
933
934        /** Tracks the Atom positions in the optimal alignment. Note: only considers the equivalent positions, gaps are ignored...
935         * first dimension is the block nr
936         * second dimension is 0 or 1 (the alignment chain index)
937         * third is the position
938         * @return int array
939         */
940        public int[][][] getOptAln()
941        {
942                return optAln;
943        }
944
945        public void setOptAln(int[][][] optAln)
946        {
947                invalidate();
948                this.optAln = optAln;
949        }
950
951        /**
952         * The length of each block
953         * @return lengths
954         */
955        public int[] getOptLen()
956        {
957                return optLen;
958        }
959
960        public void setOptLen(int[] optLen)
961        {
962                this.optLen = optLen;
963        }
964
965        public double[] getOptRmsd()
966        {
967                return optRmsd;
968        }
969
970        public void setOptRmsd(double[] optRmsd)
971        {
972                this.optRmsd = optRmsd;
973        }
974
975        public int getOptLength()
976        {
977                return optLength;
978        }
979
980        /** The length of the optimal alignment. Set by AFPOptimizer.optimizeAln().
981         * This should be the sum of the elements in optLen
982         * @param optLength
983         */
984        public void setOptLength(int optLength)
985        {
986                this.optLength = optLength;
987        }
988
989
990        public char[] getAlnsymb()
991        {
992                return alnsymb;
993        }
994
995        public void setAlnsymb(char[] alnsymb)
996        {
997                this.alnsymb = alnsymb;
998        }
999
1000
1001        public char[] getAlnseq1()
1002        {
1003                return alnseq1;
1004        }
1005
1006        public void setAlnseq1(char[] alnseq1)
1007        {
1008                this.alnseq1 = alnseq1;
1009        }
1010
1011
1012        public char[] getAlnseq2()
1013        {
1014                return alnseq2;
1015        }
1016
1017        public void setAlnseq2(char[] alnseq2)
1018        {
1019                this.alnseq2 = alnseq2;
1020        }
1021
1022
1023        /**
1024         * @return The total length of the alignment, including gaps
1025         * @see #getOptLength(), the number of aligned residues in the final alignment.
1026         */
1027        public int getAlnLength()
1028        {
1029                return alnLength;
1030        }
1031
1032        public void setAlnLength(int alnLength)
1033        {
1034                this.alnLength = alnLength;
1035        }
1036
1037        /**
1038         * @return The index of the first aligned residue in protein 1
1039         */
1040        public int getAlnbeg1()
1041        {
1042                return alnbeg1;
1043        }
1044
1045        public void setAlnbeg1(int alnbeg1)
1046        {
1047                this.alnbeg1 = alnbeg1;
1048        }
1049        /**
1050         * @return The index of the first aligned residue in protein 2
1051         */
1052        public int getAlnbeg2()
1053        {
1054                return alnbeg2;
1055        }
1056
1057        public void setAlnbeg2(int alnbeg2)
1058        {
1059                this.alnbeg2 = alnbeg2;
1060        }
1061
1062        public int getTotalLenIni()
1063        {
1064                return totalLenIni;
1065        }
1066
1067        public void setTotalLenIni(int totalLenIni)
1068        {
1069                this.totalLenIni = totalLenIni;
1070        }
1071
1072        public int getTotalLenOpt()
1073        {
1074                return totalLenOpt;
1075        }
1076
1077        public void setTotalLenOpt(int totalLenOpt)
1078        {
1079                this.totalLenOpt = totalLenOpt;
1080        }
1081
1082        /** this is the init-RMSD, not the final RMSD after refinement.
1083         *
1084         * @return totalRmsdIni
1085         */
1086        public double getTotalRmsdIni()
1087        {
1088                return totalRmsdIni;
1089        }
1090
1091        /** this is the init-RMSD, not the final RMSD after refinement.
1092         *
1093         * @param totalRmsdIni
1094         */
1095        public void setTotalRmsdIni(double totalRmsdIni)
1096        {
1097                this.totalRmsdIni = totalRmsdIni;
1098        }
1099
1100
1101        /** The RMSD of the final alignment. Use this to print overal alignment RMSD.
1102         *
1103         * @return total RMSD of the optimal alignment.
1104         */
1105        public double getTotalRmsdOpt()
1106        {
1107                return totalRmsdOpt;
1108        }
1109
1110        /** The RMSD of the final alignment. Use this to print overal alignment RMSD.
1111         *
1112         * @param totalRmsdOpt : total RMSD of the optimal alignment
1113         */
1114        public void setTotalRmsdOpt(double totalRmsdOpt)
1115        {
1116                this.totalRmsdOpt = totalRmsdOpt;
1117        }
1118
1119
1120        public String getName1()
1121        {
1122                return name1;
1123        }
1124
1125
1126        public void setName1(String name1)
1127        {
1128                this.name1 = name1;
1129        }
1130
1131
1132
1133        public String getName2()
1134        {
1135                return name2;
1136        }
1137
1138        public void setName2(String name2)
1139        {
1140                this.name2 = name2;
1141        }
1142
1143
1144        public long getCalculationTime()
1145        {
1146                return calculationTime;
1147        }
1148
1149        public void setCalculationTime(long calculationTime)
1150        {
1151                this.calculationTime = calculationTime;
1152        }
1153
1154        public int getCa1Length()
1155        {
1156                return ca1Length;
1157        }
1158
1159        public void setCa1Length(int ca1Length)
1160        {
1161                this.ca1Length = ca1Length;
1162        }
1163
1164        public int getCa2Length()
1165        {
1166                return ca2Length;
1167        }
1168
1169        public void setCa2Length(int ca2Length)
1170        {
1171                this.ca2Length = ca2Length;
1172        }
1173
1174        public long getIoTime()
1175        {
1176                return ioTime;
1177        }
1178
1179        public void setIoTime(long ioTime)
1180        {
1181                this.ioTime = ioTime;
1182        }
1183
1184        /** The probability (FATCAT) or Z-score (CE) of the alignment.
1185         *
1186         * @return either the probability (FATCAT) or the Z-score (CE) of the alignment.
1187         */
1188        public double getProbability()
1189        {
1190                return probability;
1191        }
1192
1193        public void setProbability(double probability)
1194        {
1195                this.probability = probability;
1196        }
1197
1198        /** The percent of residues that are sequence-identical in the alignment.
1199         *
1200         * @return a value between 0 and 1
1201         */
1202        public double getIdentity() {
1203                if ( identity <= 0) {
1204                        calcSimilarity();
1205                }
1206                return identity;
1207        }
1208
1209        public void setIdentity(double identity) {
1210
1211                this.identity = identity;
1212        }
1213
1214
1215        /** Returns the similarity score for the alignment. This gives the percent of
1216         * sequence similar residues in the alignment.
1217         *
1218         * @return a double between 0 and 1
1219         */
1220        public double getSimilarity() {
1221                if ( similarity < 0)
1222                        calcSimilarity();
1223                return similarity;
1224        }
1225
1226        public void setSimilarity(double similarity) {
1227                this.similarity = similarity;
1228        }
1229
1230
1231        public double getNormAlignScore()
1232        {
1233                return normAlignScore;
1234        }
1235
1236        public void setNormAlignScore(double normAlignScore)
1237        {
1238                this.normAlignScore = normAlignScore;
1239        }
1240
1241        public Matrix[] getBlockRotationMatrix()
1242        {
1243                return blockRotationMatrix;
1244        }
1245
1246        public void setBlockRotationMatrix(Matrix[] blockRotationMatrix)
1247        {
1248                this.blockRotationMatrix = blockRotationMatrix;
1249        }
1250
1251        public Atom[] getBlockShiftVector()
1252        {
1253                return blockShiftVector;
1254        }
1255
1256        public void setBlockShiftVector(Atom[] blockShiftVector)
1257        {
1258                this.blockShiftVector = blockShiftVector;
1259        }
1260
1261        public String getAlgorithmName() {
1262                return algorithmName;
1263        }
1264
1265        /**
1266         * Caution has to be made when changing the algorithmName of an AFPChain,
1267         * since downstream analysis methods (scores, display, etc) behave
1268         * differently if the alignment is flexible (created with FatCat).
1269         *
1270         * @param algorithmName
1271         */
1272        public void setAlgorithmName(String algorithmName) {
1273                this.algorithmName = algorithmName;
1274        }
1275
1276        public String getVersion() {
1277                return version;
1278        }
1279
1280        public void setVersion(String version) {
1281                this.version = version;
1282        }
1283
1284        /**
1285         * Get whether this alignment has the normal topology, ie the residues
1286         * aligned in each block increase sequentially over the original protein.
1287         *
1288         * This will be false if a circular permutation was detected.
1289         * @return true if the alignment is sequential
1290         */
1291        public boolean isSequentialAlignment() {
1292                return sequentialAlignment;
1293        }
1294        /**
1295         * Set whether this alignment has the normal topology, ie the residues
1296         * aligned in each block increase sequentially over the original protein.
1297         *
1298         * This will be false if a circular permutation was detected.
1299         */
1300        public void setSequentialAlignment(boolean sequentialAlignment) {
1301                this.sequentialAlignment = sequentialAlignment;
1302        }
1303
1304        /**
1305         * A matrix with <i>ca1length</i> rows and <i>ca2length</i> columns.
1306         * For CE this is the distance matrix, but the exact interpretation is left
1307         * up to the alignment algorithm.
1308         *
1309         * <p>Note:
1310         * A {@link org.biojava.nbio.structure.gui.JMatrixPanel}, which is used in
1311         * the structure-gui package to display distance matrices, will display the
1312         * transpose of this matrix. Be sure to take that into account when debugging
1313         * visually.
1314         *
1315         * @return A matrix with dimensions ca1length x ca2length, or null
1316         */
1317        public Matrix getDistanceMatrix() {
1318                return distanceMatrix;
1319        }
1320
1321        /**
1322         * A matrix with <i>ca1length</i> rows and <i>ca2length</i> columns.
1323         * For CE this is the distance matrix, but the exact interpretation is left
1324         * up to the alignment algorithm.
1325         * @param distanceMatrix A matrix with dimensions ca1length x ca2length
1326         */
1327        public void setDistanceMatrix(Matrix distanceMatrix) {
1328                this.distanceMatrix = distanceMatrix;
1329
1330                //System.out.println("Setting distMatrix "+(distanceMatrix==null?"null":"not null"));
1331        }
1332
1333
1334        public void setTMScore(double tmScore){
1335                this.tmScore = tmScore;
1336        }
1337
1338        /** Returns the tmScore of the alignment. If the score has not been calcualted yet,
1339         * returns -1. To calculate it call AFPChainScorer.getTMScore(afpChain, ca1, ca2);
1340         *
1341         * @return -1, if not calculated, or the TM-score, a score between 0 and 1
1342         */
1343        public double getTMScore()
1344        {
1345
1346                return tmScore;
1347        }
1348
1349
1350
1351        /** Get a textual description for the protein 2 of the alignment.
1352         *
1353         * @return
1354         */
1355        public String getDescription2() {
1356                return description2;
1357        }
1358
1359
1360        /** Set the textual description for protein 2.
1361         *
1362         * @param desc
1363         */
1364        public void setDescription2(String desc){
1365                this.description2 = desc;
1366        }
1367
1368
1369        /* (non-Javadoc)
1370         * @see java.lang.Object#hashCode()
1371         */
1372        @Override
1373        public int hashCode() {
1374                final int prime = 31;
1375                int result = 1;
1376                result = prime * result + blockNum;
1377                result = prime * result + ca1Length;
1378                result = prime * result + ca2Length;
1379                result = prime * result + Arrays.hashCode(optAln);
1380                result = prime * result + Arrays.hashCode(optLen);
1381                result = prime * result + optLength;
1382                return result;
1383        }
1384
1385        /**
1386         * A week equality metric.
1387         *
1388         * Checks if the optAlign is the same, and if the objects being compared
1389         * seem to be the same (same names, lengths). Does not check properties
1390         * of the alignment such as scores or superposition matrices.
1391         * @see java.lang.Object#equals(java.lang.Object)
1392         */
1393        @Override
1394        public boolean equals(Object obj) {
1395                if (this == obj)
1396                        return true;
1397                if (obj == null)
1398                        return false;
1399                if (getClass() != obj.getClass())
1400                        return false;
1401                AFPChain other = (AFPChain) obj;
1402                if (blockNum != other.blockNum)
1403                        return false;
1404                if (ca1Length != other.ca1Length)
1405                        return false;
1406                if (ca2Length != other.ca2Length)
1407                        return false;
1408                if (!Arrays.deepEquals(optAln, other.optAln))
1409                        return false;
1410                if (!Arrays.equals(optLen, other.optLen))
1411                        return false;
1412                if (optLength != other.optLength)
1413                        return false;
1414                return true;
1415        }
1416
1417
1418}