001/*
002 *                    BioJava 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 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 * Created on June 17, 2010
021 * Author: Mark Chapman
022 */
023
024package org.biojava.nbio.alignment.template;
025
026import org.biojava.nbio.core.alignment.template.SequencePair;
027import org.biojava.nbio.core.alignment.template.SubstitutionMatrix;
028import org.biojava.nbio.core.sequence.template.Compound;
029import org.biojava.nbio.core.sequence.template.CompoundSet;
030import org.biojava.nbio.core.sequence.template.Sequence;
031
032import java.util.ArrayList;
033import java.util.List;
034
035/**
036 * Implements common code for an {@link Aligner} for a pair of {@link Sequence}s.
037 *
038 * @author Mark Chapman
039 * @param <S> each {@link Sequence} of the alignment pair is of type S
040 * @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
041 */
042public abstract class AbstractPairwiseSequenceAligner<S extends Sequence<C>, C extends Compound>
043                extends AbstractMatrixAligner<S, C> implements PairwiseSequenceAligner<S, C> {
044
045        // additional input fields
046        private S query, target;
047
048        // additional output field
049        protected SequencePair<S, C> pair;
050
051        /**
052         * Before running a pairwise global sequence alignment, data must be sent in via calls to
053         * {@link #setQuery(Sequence)}, {@link #setTarget(Sequence)}, {@link #setGapPenalty(GapPenalty)}, and
054         * {@link #setSubstitutionMatrix(SubstitutionMatrix)}.
055         */
056        protected AbstractPairwiseSequenceAligner() {
057        }
058
059        /**
060         * Prepares for a pairwise global sequence alignment.
061         *
062         * @param query the first {@link Sequence} of the pair to align
063         * @param target the second {@link Sequence} of the pair to align
064         * @param gapPenalty the gap penalties used during alignment
065         * @param subMatrix the set of substitution scores used during alignment
066         */
067        protected AbstractPairwiseSequenceAligner(S query, S target, GapPenalty gapPenalty,
068                        SubstitutionMatrix<C> subMatrix) {
069                this(query, target, gapPenalty, subMatrix, false);
070        }
071
072        /**
073         * Prepares for a pairwise sequence alignment.
074         *
075         * @param query the first {@link Sequence} of the pair to align
076         * @param target the second {@link Sequence} of the pair to align
077         * @param gapPenalty the gap penalties used during alignment
078         * @param subMatrix the set of substitution scores used during alignment
079         * @param local if true, find a region of similarity rather than aligning every compound
080         */
081        protected AbstractPairwiseSequenceAligner(S query, S target, GapPenalty gapPenalty,
082                        SubstitutionMatrix<C> subMatrix, boolean local) {
083                super(gapPenalty, subMatrix, local);
084                this.query = query;
085                this.target = target;
086                reset();
087        }
088
089        /**
090         * Sets the query {@link Sequence}.
091         *
092         * @param query the first {@link Sequence} of the pair to align
093         */
094        public void setQuery(S query) {
095                this.query = query;
096                reset();
097        }
098
099        /**
100         * Sets the target {@link Sequence}.
101         *
102         * @param target the second {@link Sequence} of the pair to align
103         */
104        public void setTarget(S target) {
105                this.target = target;
106                reset();
107        }
108
109        // method for PairwiseSequenceAligner
110
111        @Override
112        public SequencePair<S, C> getPair() {
113                if (pair == null) {
114                        align();
115                }
116                return pair;
117        }
118
119        // methods for PairwiseSequenceScorer
120
121        @Override
122        public S getQuery() {
123                return query;
124        }
125
126        @Override
127        public S getTarget() {
128                return target;
129        }
130
131        // methods for AbstractMatrixAligner
132
133        @Override
134        protected CompoundSet<C> getCompoundSet() {
135                return (query == null) ? null : query.getCompoundSet();
136        }
137
138        @Override
139        protected List<C> getCompoundsOfQuery() {
140                return (query == null) ? new ArrayList<C>() : query.getAsList();
141        }
142
143        @Override
144        protected List<C> getCompoundsOfTarget() {
145                return (target == null) ? new ArrayList<C>() : target.getAsList();
146        }
147
148        @Override
149        protected int[] getScoreMatrixDimensions() {
150                return new int[] { (query == null) ? 1 : query.getLength() + 1, (target == null) ? 1 : target.getLength() + 1,
151                                (getGapPenalty() == null || getGapPenalty().getType() == GapPenalty.Type.LINEAR) ? 1 : 3 };
152        }
153
154        @Override
155        protected int getSubstitutionScore(int queryColumn, int targetColumn) {
156                return getSubstitutionMatrix().getValue(query.getCompoundAt(queryColumn), target.getCompoundAt(targetColumn));
157        }
158
159        @Override
160        protected boolean isReady() {
161                return query != null && target != null && getGapPenalty() != null && getSubstitutionMatrix() != null &&
162                                query.getCompoundSet().equals(target.getCompoundSet());
163        }
164
165        @Override
166        protected void reset() {
167                super.reset();
168                pair = null;
169                if (query != null && target != null && getGapPenalty() != null && getSubstitutionMatrix() != null &&
170                                query.getCompoundSet().equals(target.getCompoundSet())) {
171                        int maxq = 0, maxt = 0;
172                        for (C c : query) {
173                                maxq += getSubstitutionMatrix().getValue(c, c);
174                        }
175                        for (C c : target) {
176                                maxt += getSubstitutionMatrix().getValue(c, c);
177                        }
178                        max = Math.max(maxq, maxt);
179                        score = min = isLocal() ? 0 : (int) (2 * getGapPenalty().getOpenPenalty() + (query.getLength() +
180                                        target.getLength()) * getGapPenalty().getExtensionPenalty());
181                }
182        }
183
184}