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