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