/*
* BioJava development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public Licence. This should
* be distributed with the code. If you do not have a copy,
* see:
*
* http://www.gnu.org/copyleft/lesser.html
*
* Copyright for this code is held jointly by the individual
* authors. These should be listed in @author doc comments.
*
* For more information on the BioJava project and its aims,
* or to join the biojava-l mailing list, visit the home page
* at:
*
* http://www.biojava.org/
*
* Created on June 7, 2010
* Author: Mark Chapman
*/
package org.biojava.nbio.alignment;
import org.biojava.nbio.core.alignment.template.ProfilePair;
import org.biojava.nbio.core.alignment.template.SequencePair;
import org.biojava.nbio.core.alignment.matrices.SubstitutionMatrixHelper;
import org.biojava.nbio.core.alignment.template.Profile;
import org.biojava.nbio.core.alignment.template.SubstitutionMatrix;
import org.biojava.nbio.alignment.template.*;
import org.biojava.nbio.core.sequence.compound.AmbiguityDNACompoundSet;
import org.biojava.nbio.core.sequence.compound.AminoAcidCompoundSet;
import org.biojava.nbio.core.sequence.compound.DNACompoundSet;
import org.biojava.nbio.core.sequence.template.Compound;
import org.biojava.nbio.core.sequence.template.CompoundSet;
import org.biojava.nbio.core.sequence.template.Sequence;
import org.biojava.nbio.core.util.ConcurrencyTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* Static utility to easily run alignment routines. To exit cleanly after running any parallel method that mentions
* use of the {@link ConcurrencyTools} utility, {@link ConcurrencyTools#shutdown()} or
* {@link ConcurrencyTools#shutdownAndAwaitTermination()} must be called.
*
* @author Mark Chapman
*/
public class Alignments {
private final static Logger logger = LoggerFactory.getLogger(Alignments.class);
/**
* List of implemented sequence pair in a profile scoring routines.
*/
public static enum PairInProfileScorerType {
IDENTITIES, // similar to MUSCLE
SIMILARITIES
}
/**
* List of implemented pairwise sequence alignment routines.
*/
public static enum PairwiseSequenceAlignerType {
GLOBAL, // Needleman-Wunsch/Gotoh
GLOBAL_LINEAR_SPACE, // Guan-Uberbacher
LOCAL, // Smith-Waterman/Gotoh
LOCAL_LINEAR_SPACE // Smith-Waterman/Gotoh with smart traceback at each maximum
}
/**
* List of implemented pairwise sequence scoring routines.
*/
public static enum PairwiseSequenceScorerType {
GLOBAL,
GLOBAL_IDENTITIES, // similar to CLUSTALW and CLUSTALW2
GLOBAL_SIMILARITIES,
LOCAL,
LOCAL_IDENTITIES,
LOCAL_SIMILARITIES,
KMERS, // similar to CLUSTAL and MUSCLE
WU_MANBER // similar to KALIGN
}
/**
* List of implemented profile-profile alignment routines.
*/
public static enum ProfileProfileAlignerType {
GLOBAL, // similar to MUSCLE and KALIGN
GLOBAL_LINEAR_SPACE, // similar to CLUSTALW and CLUSTALW2
GLOBAL_CONSENSUS, // similar to CLUSTAL
LOCAL,
LOCAL_LINEAR_SPACE,
LOCAL_CONSENSUS
}
/**
* List of implemented profile refinement routines.
*/
public static enum RefinerType {
PARTITION_SINGLE, // similar to CLUSTALW2
PARTITION_SINGLE_ALL, // similar to CLUSTALW2
PARTITION_TREE, // similar to MUSCLE
PARTITION_TREE_ALL,
RESCORE_IDENTITIES, // similar to MUSCLE
RESCORE_SIMILARITIES
}
// prevents instantiation
private Alignments() { }
// public factory methods
/**
* Factory method which computes a sequence alignment for all {@link Sequence} pairs in the given {@link List}.
* This method runs the alignments in parallel by submitting all of the alignments to the shared thread pool of the
* {@link ConcurrencyTools} utility.
*
* @param <S> each {@link Sequence} of an alignment pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param sequences the {@link List} of {@link Sequence}s to align
* @param type chosen type from list of pairwise sequence alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return list of sequence alignment pairs
*/
public static <S extends Sequence<C>, C extends Compound> List<SequencePair<S, C>> getAllPairsAlignments(
List<S> sequences, PairwiseSequenceAlignerType type, GapPenalty gapPenalty,
SubstitutionMatrix<C> subMatrix) {
return runPairwiseAligners(getAllPairsAligners(sequences, type, gapPenalty, subMatrix));
}
/**
* Factory method which computes a multiple sequence alignment for the given {@link List} of {@link Sequence}s.
*
* @param <S> each {@link Sequence} of the {@link List} is of type S
* @param <C> each element of a {@link Sequence} is a {@link Compound} of type C
* @param sequences the {@link List} of {@link Sequence}s to align
* @param settings optional settings that adjust the alignment
* @return multiple sequence alignment {@link Profile}
*/
public static <S extends Sequence<C>, C extends Compound> Profile<S, C> getMultipleSequenceAlignment(
List<S> sequences, Object... settings) { // TODO convert other factories to this parameter style?
CompoundSet<C> cs = sequences.get(0).getCompoundSet();
PairwiseSequenceScorerType ps = PairwiseSequenceScorerType.GLOBAL_IDENTITIES;
GapPenalty gapPenalty = new SimpleGapPenalty();
SubstitutionMatrix<C> subMatrix = null;
if (cs == AminoAcidCompoundSet.getAminoAcidCompoundSet()) {
@SuppressWarnings("unchecked") // compound types must be equal since compound sets are equal
SubstitutionMatrix<C> temp = (SubstitutionMatrix<C>) SubstitutionMatrixHelper.getBlosum62();
subMatrix = temp;
} else if (cs == DNACompoundSet.getDNACompoundSet()) {
@SuppressWarnings("unchecked") // compound types must be equal since compound sets are equal
SubstitutionMatrix<C> temp = (SubstitutionMatrix<C>) SubstitutionMatrixHelper.getNuc4_4();
subMatrix = temp;
} else if (cs == AmbiguityDNACompoundSet.getDNACompoundSet()) {
@SuppressWarnings("unchecked") // compound types must be equal since compound sets are equal
SubstitutionMatrix<C> temp = (SubstitutionMatrix<C>) SubstitutionMatrixHelper.getNuc4_4();
subMatrix = temp;
}
ProfileProfileAlignerType pa = ProfileProfileAlignerType.GLOBAL;
for (Object o : settings) {
if (o instanceof PairwiseSequenceScorerType) {
ps = (PairwiseSequenceScorerType) o;
} else if (o instanceof GapPenalty) {
gapPenalty = (GapPenalty) o;
} else if (o instanceof SubstitutionMatrix<?>) {
if (cs != ((SubstitutionMatrix<?>) o).getCompoundSet()) {
throw new IllegalArgumentException(
"Compound sets of the sequences and substitution matrix must match.");
}
@SuppressWarnings("unchecked") // compound types must be equal since compound sets are equal
SubstitutionMatrix<C> temp = (SubstitutionMatrix<C>) o;
subMatrix = temp;
} else if (o instanceof ProfileProfileAlignerType) {
pa = (ProfileProfileAlignerType) o;
}
}
// stage 1: pairwise similarity calculation
List<PairwiseSequenceScorer<S, C>> scorers = getAllPairsScorers(sequences, ps, gapPenalty, subMatrix);
runPairwiseScorers(scorers);
// stage 2: hierarchical clustering into a guide tree
GuideTree<S, C> tree = new GuideTree<S, C>(sequences, scorers);
scorers = null;
// stage 3: progressive alignment
Profile<S, C> msa = getProgressiveAlignment(tree, pa, gapPenalty, subMatrix);
// TODO stage 4: refinement
return msa;
}
/**
* Factory method which computes a sequence alignment for the given {@link Sequence} pair.
*
* @param <S> each {@link Sequence} of the pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param query the first {@link Sequence}s to align
* @param target the second {@link Sequence}s to align
* @param type chosen type from list of pairwise sequence alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return sequence alignment pair
*/
public static <S extends Sequence<C>, C extends Compound> SequencePair<S, C> getPairwiseAlignment(
S query, S target, PairwiseSequenceAlignerType type, GapPenalty gapPenalty,
SubstitutionMatrix<C> subMatrix) {
return getPairwiseAligner(query, target, type, gapPenalty, subMatrix).getPair();
}
// default access (package private) factory methods
/**
* Factory method which sets up a sequence alignment for all {@link Sequence} pairs in the given {@link List}.
*
* @param <S> each {@link Sequence} of an alignment pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param sequences the {@link List} of {@link Sequence}s to align
* @param type chosen type from list of pairwise sequence alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return list of pairwise sequence aligners
*/
static <S extends Sequence<C>, C extends Compound> List<PairwiseSequenceAligner<S, C>> getAllPairsAligners(
List<S> sequences, PairwiseSequenceAlignerType type, GapPenalty gapPenalty,
SubstitutionMatrix<C> subMatrix) {
List<PairwiseSequenceAligner<S, C>> allPairs = new ArrayList<PairwiseSequenceAligner<S, C>>();
for (int i = 0; i < sequences.size(); i++) {
for (int j = i+1; j < sequences.size(); j++) {
allPairs.add(getPairwiseAligner(sequences.get(i), sequences.get(j), type, gapPenalty, subMatrix));
}
}
return allPairs;
}
/**
* Factory method which sets up a sequence pair scorer for all {@link Sequence} pairs in the given {@link List}.
*
* @param <S> each {@link Sequence} of a pair is of type S
* @param <C> each element of a {@link Sequence} is a {@link Compound} of type C
* @param sequences the {@link List} of {@link Sequence}s to align
* @param type chosen type from list of pairwise sequence scoring routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return list of sequence pair scorers
*/
public static <S extends Sequence<C>, C extends Compound> List<PairwiseSequenceScorer<S, C>> getAllPairsScorers(
List<S> sequences, PairwiseSequenceScorerType type, GapPenalty gapPenalty,
SubstitutionMatrix<C> subMatrix) {
List<PairwiseSequenceScorer<S, C>> allPairs = new ArrayList<PairwiseSequenceScorer<S, C>>();
for (int i = 0; i < sequences.size(); i++) {
for (int j = i+1; j < sequences.size(); j++) {
allPairs.add(getPairwiseScorer(sequences.get(i), sequences.get(j), type, gapPenalty, subMatrix));
}
}
return allPairs;
}
/**
* Factory method which computes a sequence pair score for all {@link Sequence} pairs in the given {@link List}.
* This method runs the scorings in parallel by submitting all of the scorings to the shared thread pool of the
* {@link ConcurrencyTools} utility.
*
* @param <S> each {@link Sequence} of a pair is of type S
* @param <C> each element of a {@link Sequence} is a {@link Compound} of type C
* @param sequences the {@link List} of {@link Sequence}s to align
* @param type chosen type from list of pairwise sequence scoring routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return list of sequence pair scores
*/
public static <S extends Sequence<C>, C extends Compound> double[] getAllPairsScores( List<S> sequences,
PairwiseSequenceScorerType type, GapPenalty gapPenalty, SubstitutionMatrix<C> subMatrix) {
return runPairwiseScorers(getAllPairsScorers(sequences, type, gapPenalty, subMatrix));
}
/**
* Factory method which retrieves calculated elements from a list of tasks on the concurrent execution queue.
*
* @param <E> each task calculates a value of type E
* @param futures list of tasks
* @return calculated elements
*/
static <E> List<E> getListFromFutures(List<Future<E>> futures) {
List<E> list = new ArrayList<E>();
for (Future<E> f : futures) {
// TODO when added to ConcurrencyTools, log completions and exceptions instead of printing stack traces
try {
list.add(f.get());
} catch (InterruptedException e) {
logger.error("Interrupted Exception: ", e);
} catch (ExecutionException e) {
logger.error("Execution Exception: ", e);
}
}
return list;
}
/**
* Factory method which constructs a pairwise sequence aligner.
*
* @param <S> each {@link Sequence} of an alignment pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param query the first {@link Sequence} to align
* @param target the second {@link Sequence} to align
* @param type chosen type from list of pairwise sequence alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return pairwise sequence aligner
*/
public static <S extends Sequence<C>, C extends Compound> PairwiseSequenceAligner<S, C> getPairwiseAligner(
S query, S target, PairwiseSequenceAlignerType type, GapPenalty gapPenalty,
SubstitutionMatrix<C> subMatrix) {
if (!query.getCompoundSet().equals(target.getCompoundSet())) {
throw new IllegalArgumentException("Sequence compound sets must be the same");
}
switch (type) {
default:
case GLOBAL:
return new NeedlemanWunsch<S, C>(query, target, gapPenalty, subMatrix);
case LOCAL:
return new SmithWaterman<S, C>(query, target, gapPenalty, subMatrix);
case GLOBAL_LINEAR_SPACE:
case LOCAL_LINEAR_SPACE:
// TODO other alignment options (Myers-Miller, Thompson)
throw new UnsupportedOperationException(Alignments.class.getSimpleName() + " does not yet support " +
type + " alignment");
}
}
/**
* Factory method which computes a similarity score for the given {@link Sequence} pair.
*
* @param <S> each {@link Sequence} of the pair is of type S
* @param <C> each element of a {@link Sequence} is a {@link Compound} of type C
* @param query the first {@link Sequence} to score
* @param target the second {@link Sequence} to score
* @param type chosen type from list of pairwise sequence scoring routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return sequence pair score
*/
static <S extends Sequence<C>, C extends Compound> double getPairwiseScore(S query, S target,
PairwiseSequenceScorerType type, GapPenalty gapPenalty, SubstitutionMatrix<C> subMatrix) {
return getPairwiseScorer(query, target, type, gapPenalty, subMatrix).getScore();
}
/**
* Factory method which constructs a pairwise sequence scorer.
*
* @param <S> each {@link Sequence} of a pair is of type S
* @param <C> each element of a {@link Sequence} is a {@link Compound} of type C
* @param query the first {@link Sequence} to score
* @param target the second {@link Sequence} to score
* @param type chosen type from list of pairwise sequence scoring routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return sequence pair scorer
*/
static <S extends Sequence<C>, C extends Compound> PairwiseSequenceScorer<S, C> getPairwiseScorer(
S query, S target, PairwiseSequenceScorerType type, GapPenalty gapPenalty,
SubstitutionMatrix<C> subMatrix) {
switch (type) {
default:
case GLOBAL:
return getPairwiseAligner(query, target, PairwiseSequenceAlignerType.GLOBAL, gapPenalty, subMatrix);
case GLOBAL_IDENTITIES:
return new FractionalIdentityScorer<S, C>(getPairwiseAligner(query, target,
PairwiseSequenceAlignerType.GLOBAL, gapPenalty, subMatrix));
case GLOBAL_SIMILARITIES:
return new FractionalSimilarityScorer<S, C>(getPairwiseAligner(query, target,
PairwiseSequenceAlignerType.GLOBAL, gapPenalty, subMatrix));
case LOCAL:
return getPairwiseAligner(query, target, PairwiseSequenceAlignerType.LOCAL, gapPenalty, subMatrix);
case LOCAL_IDENTITIES:
return new FractionalIdentityScorer<S, C>(getPairwiseAligner(query, target,
PairwiseSequenceAlignerType.LOCAL, gapPenalty, subMatrix));
case LOCAL_SIMILARITIES:
return new FractionalSimilarityScorer<S, C>(getPairwiseAligner(query, target,
PairwiseSequenceAlignerType.LOCAL, gapPenalty, subMatrix));
case KMERS:
case WU_MANBER:
// TODO other scoring options
throw new UnsupportedOperationException(Alignments.class.getSimpleName() + " does not yet support " +
type + " scoring");
}
}
/**
* Factory method which constructs a profile-profile aligner.
*
* @param <S> each {@link Sequence} of an alignment profile is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param profile1 the first {@link Profile} to align
* @param profile2 the second {@link Profile} to align
* @param type chosen type from list of profile-profile alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return profile-profile aligner
*/
static <S extends Sequence<C>, C extends Compound> ProfileProfileAligner<S, C> getProfileProfileAligner(
Profile<S, C> profile1, Profile<S, C> profile2, ProfileProfileAlignerType type, GapPenalty gapPenalty,
SubstitutionMatrix<C> subMatrix) {
switch (type) {
default:
case GLOBAL:
return new SimpleProfileProfileAligner<S, C>(profile1, profile2, gapPenalty, subMatrix);
case GLOBAL_LINEAR_SPACE:
case GLOBAL_CONSENSUS:
case LOCAL:
case LOCAL_LINEAR_SPACE:
case LOCAL_CONSENSUS:
// TODO other alignment options (Myers-Miller, consensus, local)
throw new UnsupportedOperationException(Alignments.class.getSimpleName() + " does not yet support " +
type + " alignment");
}
}
/**
* Factory method which constructs a profile-profile aligner.
*
* @param <S> each {@link Sequence} of an alignment profile is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param profile1 the first {@link Profile} to align
* @param profile2 the second {@link Profile} to align
* @param type chosen type from list of profile-profile alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return profile-profile aligner
*/
static <S extends Sequence<C>, C extends Compound> ProfileProfileAligner<S, C> getProfileProfileAligner(
Future<ProfilePair<S, C>> profile1, Future<ProfilePair<S, C>> profile2, ProfileProfileAlignerType type,
GapPenalty gapPenalty, SubstitutionMatrix<C> subMatrix) {
switch (type) {
default:
case GLOBAL:
return new SimpleProfileProfileAligner<S, C>(profile1, profile2, gapPenalty, subMatrix);
case GLOBAL_LINEAR_SPACE:
case GLOBAL_CONSENSUS:
case LOCAL:
case LOCAL_LINEAR_SPACE:
case LOCAL_CONSENSUS:
// TODO other alignment options (Myers-Miller, consensus, local)
throw new UnsupportedOperationException(Alignments.class.getSimpleName() + " does not yet support " +
type + " alignment");
}
}
/**
* Factory method which constructs a profile-profile aligner.
*
* @param <S> each {@link Sequence} of an alignment profile is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param profile1 the first {@link Profile} to align
* @param profile2 the second {@link Profile} to align
* @param type chosen type from list of profile-profile alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return profile-profile aligner
*/
static <S extends Sequence<C>, C extends Compound> ProfileProfileAligner<S, C> getProfileProfileAligner(
Profile<S, C> profile1, Future<ProfilePair<S, C>> profile2, ProfileProfileAlignerType type,
GapPenalty gapPenalty, SubstitutionMatrix<C> subMatrix) {
switch (type) {
default:
case GLOBAL:
return new SimpleProfileProfileAligner<S, C>(profile1, profile2, gapPenalty, subMatrix);
case GLOBAL_LINEAR_SPACE:
case GLOBAL_CONSENSUS:
case LOCAL:
case LOCAL_LINEAR_SPACE:
case LOCAL_CONSENSUS:
// TODO other alignment options (Myers-Miller, consensus, local)
throw new UnsupportedOperationException(Alignments.class.getSimpleName() + " does not yet support " +
type + " alignment");
}
}
/**
* Factory method which constructs a profile-profile aligner.
*
* @param <S> each {@link Sequence} of an alignment profile is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param profile1 the first {@link Profile} to align
* @param profile2 the second {@link Profile} to align
* @param type chosen type from list of profile-profile alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return profile-profile aligner
*/
static <S extends Sequence<C>, C extends Compound> ProfileProfileAligner<S, C> getProfileProfileAligner(
Future<ProfilePair<S, C>> profile1, Profile<S, C> profile2, ProfileProfileAlignerType type,
GapPenalty gapPenalty, SubstitutionMatrix<C> subMatrix) {
switch (type) {
default:
case GLOBAL:
return new SimpleProfileProfileAligner<S, C>(profile1, profile2, gapPenalty, subMatrix);
case GLOBAL_LINEAR_SPACE:
case GLOBAL_CONSENSUS:
case LOCAL:
case LOCAL_LINEAR_SPACE:
case LOCAL_CONSENSUS:
// TODO other alignment options (Myers-Miller, consensus, local)
throw new UnsupportedOperationException(Alignments.class.getSimpleName() + " does not yet support " +
type + " alignment");
}
}
/**
* Factory method which computes a profile alignment for the given {@link Profile} pair.
*
* @param <S> each {@link Sequence} of the {@link Profile} pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param profile1 the first {@link Profile} to align
* @param profile2 the second {@link Profile} to align
* @param type chosen type from list of profile-profile alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return alignment profile
*/
static <S extends Sequence<C>, C extends Compound> ProfilePair<S, C> getProfileProfileAlignment(
Profile<S, C> profile1, Profile<S, C> profile2, ProfileProfileAlignerType type, GapPenalty gapPenalty,
SubstitutionMatrix<C> subMatrix) {
return getProfileProfileAligner(profile1, profile2, type, gapPenalty, subMatrix).getPair();
}
/**
* Factory method to run the profile-profile alignments of a progressive multiple sequence alignment concurrently.
* This method runs the alignments in parallel by submitting all of the alignment tasks to the shared thread pool
* of the {@link ConcurrencyTools} utility.
*
* @param <S> each {@link Sequence} of the {@link Profile} pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param tree guide tree to follow aligning profiles from leaves to root
* @param type chosen type from list of profile-profile alignment routines
* @param gapPenalty the gap penalties used during alignment
* @param subMatrix the set of substitution scores used during alignment
* @return multiple sequence alignment
*/
public static <S extends Sequence<C>, C extends Compound> Profile<S, C> getProgressiveAlignment(GuideTree<S, C> tree,
ProfileProfileAlignerType type, GapPenalty gapPenalty, SubstitutionMatrix<C> subMatrix) {
// find inner nodes in post-order traversal of tree (each leaf node has a single sequence profile)
List<GuideTreeNode<S, C>> innerNodes = new ArrayList<GuideTreeNode<S, C>>();
for (GuideTreeNode<S, C> n : tree) {
if (n.getProfile() == null) {
innerNodes.add(n);
}
}
// submit alignment tasks to the shared thread pool
int i = 1, all = innerNodes.size();
for (GuideTreeNode<S, C> n : innerNodes) {
Profile<S, C> p1 = n.getChild1().getProfile(), p2 = n.getChild2().getProfile();
Future<ProfilePair<S, C>> pf1 = n.getChild1().getProfileFuture(), pf2 = n.getChild2().getProfileFuture();
ProfileProfileAligner<S, C> aligner =
(p1 != null) ? ((p2 != null) ? getProfileProfileAligner(p1, p2, type, gapPenalty, subMatrix) :
getProfileProfileAligner(p1, pf2, type, gapPenalty, subMatrix)) :
((p2 != null) ? getProfileProfileAligner(pf1, p2, type, gapPenalty, subMatrix) :
getProfileProfileAligner(pf1, pf2, type, gapPenalty, subMatrix));
n.setProfileFuture(ConcurrencyTools.submit(new CallableProfileProfileAligner<S, C>(aligner), String.format(
"Aligning pair %d of %d", i++, all)));
}
// retrieve the alignment results
for (GuideTreeNode<S, C> n : innerNodes) {
// TODO when added to ConcurrencyTools, log completions and exceptions instead of printing stack traces
try {
n.setProfile(n.getProfileFuture().get());
} catch (InterruptedException e) {
logger.error("Interrupted Exception: ", e);
} catch (ExecutionException e) {
logger.error("Execution Exception: ", e);
}
}
// the alignment profile at the root of the tree is the full multiple sequence alignment
return tree.getRoot().getProfile();
}
/**
* Factory method to run a list of alignments concurrently. This method runs the alignments in parallel by
* submitting all of the alignment tasks to the shared thread pool of the {@link ConcurrencyTools} utility.
*
* @param <S> each {@link Sequence} of an alignment pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param aligners list of alignments to run
* @return list of {@link SequencePair} results from running alignments
*/
static <S extends Sequence<C>, C extends Compound> List<SequencePair<S, C>>
runPairwiseAligners(List<PairwiseSequenceAligner<S, C>> aligners) {
int n = 1, all = aligners.size();
List<Future<SequencePair<S, C>>> futures = new ArrayList<Future<SequencePair<S, C>>>();
for (PairwiseSequenceAligner<S, C> aligner : aligners) {
futures.add(ConcurrencyTools.submit(new CallablePairwiseSequenceAligner<S, C>(aligner),
String.format("Aligning pair %d of %d", n++, all)));
}
return getListFromFutures(futures);
}
/**
* Factory method to run a list of scorers concurrently. This method runs the scorers in parallel by submitting
* all of the scoring tasks to the shared thread pool of the {@link ConcurrencyTools} utility.
*
* @param <S> each {@link Sequence} of an alignment pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param scorers list of scorers to run
* @return list of score results from running scorers
*/
public static <S extends Sequence<C>, C extends Compound> double[] runPairwiseScorers(
List<PairwiseSequenceScorer<S, C>> scorers) {
int n = 1, all = scorers.size();
List<Future<Double>> futures = new ArrayList<Future<Double>>();
for (PairwiseSequenceScorer<S, C> scorer : scorers) {
futures.add(ConcurrencyTools.submit(new CallablePairwiseSequenceScorer<S, C>(scorer),
String.format("Scoring pair %d of %d", n++, all)));
}
List<Double> results = getListFromFutures(futures);
double[] scores = new double[results.size()];
for (int i = 0; i < scores.length; i++) {
scores[i] = results.get(i);
}
return scores;
}
/**
* Factory method to run a list of alignments concurrently. This method runs the alignments in parallel by
* submitting all of the alignment tasks to the shared thread pool of the {@link ConcurrencyTools} utility.
*
* @param <S> each {@link Sequence} of the {@link Profile} pair is of type S
* @param <C> each element of an {@link AlignedSequence} is a {@link Compound} of type C
* @param aligners list of alignments to run
* @return list of {@link ProfilePair} results from running alignments
*/
static <S extends Sequence<C>, C extends Compound> List<ProfilePair<S, C>>
runProfileAligners(List<ProfileProfileAligner<S, C>> aligners) {
int n = 1, all = aligners.size();
List<Future<ProfilePair<S, C>>> futures = new ArrayList<Future<ProfilePair<S, C>>>();
for (ProfileProfileAligner<S, C> aligner : aligners) {
futures.add(ConcurrencyTools.submit(new CallableProfileProfileAligner<S, C>(aligner),
String.format("Aligning pair %d of %d", n++, all)));
}
return getListFromFutures(futures);
}
}