Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package calhoun.bean;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import calhoun.bean.impl.SequenceStringGenerator;
- import calhoun.mapping.castor.CastorClass;
- import calhoun.mapping.castor.CastorCollection;
- import calhoun.mapping.castor.CastorEnums;
- import calhoun.mapping.castor.CastorField;
- import calhoun.mapping.castor.CastorEnums.CollectionType;
- import calhoun.mapping.hibernate.HibernateClass;
- import calhoun.mapping.hibernate.HibernateCollection;
- import calhoun.mapping.hibernate.HibernateEnums;
- import calhoun.mapping.hibernate.HibernateId;
- import calhoun.mapping.hibernate.HibernateManyToMany;
- import calhoun.mapping.hibernate.HibernateProperty;
- import calhoun.mapping.hibernate.HibernateEnums.CascadeType;
- import calhoun.util.Assert;
- import calhoun.util.CheckException;
- import calhoun.util.Checkable;
- import calhoun.util.StringUtil;
- /**
- * A MultipleAlignment is a collection of HalfAlignments all aligned to a single
- * reference frame.
- *
- * TODO: more documentation
- *
- * @author aroberts
- *
- */
- @CastorClass(isAutoComplete = false, idProperty = "ref")
- @HibernateClass(table = "ap_multiple_alignment")
- public class MultipleAlignment extends AbstractEntity implements Checkable {
- public static interface FeatureLabeler {
- public String label(Feature f);
- }
- public static class OutputOptions {
- private boolean includePositionIndexes;
- private FeatureLabeler labeler;
- private int width;
- public OutputOptions() {
- this.width = 60;
- this.labeler = new FeatureLabeler() {
- public String label(Feature f) {
- return f.getName();
- }
- };
- this.includePositionIndexes = false;
- }
- public FeatureLabeler getLabeler() {
- return labeler;
- }
- public int getWidth() {
- return width;
- }
- public boolean isIncludePositionIndexes() {
- return includePositionIndexes;
- }
- public OutputOptions setIncludePositionIndexes(
- boolean includePositionIndexes) {
- this.includePositionIndexes = includePositionIndexes;
- return this;
- }
- public OutputOptions setLabeler(FeatureLabeler labeler) {
- this.labeler = labeler;
- return this;
- }
- public OutputOptions setWidth(int width) {
- this.width = width;
- return this;
- }
- }
- private List<? extends HalfAlignment> alignments;
- private String consensus;
- private String id;
- private Integer length = null;
- public MultipleAlignment() {
- }
- public MultipleAlignment(List<? extends HalfAlignment> alignments) {
- this(alignments, null);
- }
- /**
- * Construct a new MultipleAlignment from a list of HalfAlignments and a
- * consensus sequence. The consensus sequence is meant to be passed in from an
- * aligner, which should do a better job of generating it than we would here
- * in the code. The consensus may be null.
- *
- * @param alignments
- * the component HalfAlignments of this MultipleAlignment
- * @param consensus
- * a sequence to use as the consensus string
- */
- public MultipleAlignment(List<? extends HalfAlignment> alignments,
- String consensus) {
- this.alignments = Collections.unmodifiableList(alignments);
- length = calculateLength();
- this.consensus = consensus;
- }
- private Integer calculateLength() {
- return alignments.iterator().next().getLength();
- }
- public void check() {
- validate();
- for (HalfAlignment a : alignments) {
- a.check();
- }
- }
- @CastorField(xmlName = "half-alignment")
- @CastorCollection(elementType = HalfAlignment.class, collectionType = CollectionType.ARRAYLIST)
- @HibernateCollection(elementType = HalfAlignment.class, cascade = CascadeType.SAVE_UPDATE, collectionType = HibernateEnums.CollectionType.LIST)
- @HibernateManyToMany(joinTable = "ap_multiple_alignment_member", ownerColumn = "ap_multiple_alignment_id", referenceColumn = "ap_half_alignment_id", indexColumn = "ap_index")
- public List<? extends HalfAlignment> getAlignments() {
- return alignments;
- }
- @HibernateProperty(column = "ap_consensus")
- public String getConsensus() {
- return consensus;
- }
- @Override
- @CastorField(nodeType = CastorEnums.NodeType.ATTRIBUTE)
- @HibernateId(column = "ap_id", generator = SequenceStringGenerator.class, sequence = "ap_multiple_alignment_seq")
- public String getId() {
- return id;
- }
- @Override
- public Class<? extends Object> getIdType() {
- return MultipleAlignment.class;
- }
- /**
- * Returns the length of the alignment coordinate frame for this alignment. In
- * a visual sense, this is the width of the 'rectangle' of sequence formed by
- * this multiple alignment.
- *
- * @return the length of the alignment
- */
- public int getLength() {
- if (length == null) {
- length = calculateLength();
- }
- return length;
- }
- /**
- * This method is required by castor and not designed for programmer use.
- *
- * @param alignments
- */
- public void setAlignments(List<? extends HalfAlignment> alignments) {
- this.alignments = alignments;
- }
- public void setConsensus(String consensus) {
- this.consensus = consensus;
- }
- public void setId(String id) {
- this.id = id;
- }
- /**
- * Creates a new MultipleAlignment object as a partition of this
- * MultipleAlignment. The new MultipleAlignment will contain slices of all of
- * the contained HalfAlignments at the specified coordinates.
- *
- * Given a multiple Alignment <code>m</code>:
- *
- * <pre>
- * 12345678901
- * AATACGCGGGC
- * AAGA-GGCGGC
- * AAT----CGGG
- * </pre>
- *
- * Calling <code>m.slice(3,7)</code> gives us this MultipleAlignment:
- *
- * <pre>
- * 12345
- * TACGC
- * GA-GG
- * T----
- * </pre>
- *
- * @param start
- * 1-based start coordinate
- * @param stop
- * 1-based stop coordinate
- * @return a new MultipleAlignment, cut from the old MultipleAlignment at the
- * specified coordinates
- */
- public MultipleAlignment slice(int start, int stop) {
- List<HalfAlignment> newSet = new ArrayList<HalfAlignment>();
- for (HalfAlignment h : getAlignments()) {
- HalfAlignment newHalf = h.slice(start, stop);
- newSet.add(newHalf);
- }
- String newConsensus = getConsensus().substring(start - 1, stop);
- return new MultipleAlignment(newSet, newConsensus);
- }
- @Override
- public String toString() {
- return toString(new OutputOptions());
- }
- public String toString(OutputOptions options) {
- String separator = " ";
- int start = 0;
- int maxLabelLength = 0;
- FeatureLabeler labeler = options.getLabeler();
- int width = options.getWidth();
- StringBuilder sb = new StringBuilder();
- // find max label length
- for (HalfAlignment h : alignments) {
- Assert.a(labeler.label(h) != null,
- "Labeler produced a null label for feature " + h.getId());
- maxLabelLength = Math.max(maxLabelLength, labeler.label(h).length());
- }
- while (start < getLength()) {
- int end = Math.min(start + width, getLength());
- // optionally, include a '1234567890...' count above the alignment to make
- // it easy to find specific positions
- if (options.isIncludePositionIndexes()) {
- sb.append(StringUtil.repeatChars(maxLabelLength, ' '));
- sb.append(separator);
- for (int i = 1; i <= end - start; i++) {
- sb.append(i % 10);
- }
- sb.append("\n");
- }
- for (HalfAlignment h : alignments) {
- String label = labeler.label(h);
- sb.append(label);
- sb.append(StringUtil.repeatChars(maxLabelLength - label.length(), ' '));
- sb.append(separator);
- sb.append(h.getTransformedSequence().substring(start, end));
- sb.append("\n");
- }
- sb.append("\n");
- start = end;
- }
- return sb.toString();
- }
- public void validate() {
- for (HalfAlignment a : alignments) {
- Assert.a(a.getLength() == getLength(), String.format(
- "HalfAlignment %s is not the same length as this multiple alignment",
- a.getId()));
- }
- Assert
- .a(
- consensus.length() == getLength(),
- String
- .format(
- "Consensus is not the same length as the half alignments - %d instead of %d",
- consensus.length(), getLength()));
- }
- public boolean valid() {
- try {
- validate();
- return true;
- } catch (CheckException e) {
- return false;
- }
- }
- }
Add Comment
Please, Sign In to add comment