Package bgu.bio.ds.rna

Source Code of bgu.bio.ds.rna.StemStructure$StemStructureShuffleData

package bgu.bio.ds.rna;

import gnu.trove.list.array.TCharArrayList;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TIntObjectHashMap;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import bgu.bio.adt.queue.Pool;
import bgu.bio.adt.tuples.IntPair;
import bgu.bio.util.CharBuffer;
import bgu.bio.util.alphabet.StemStructureAlphabet;

public class StemStructure {
  private static Pool<InnerStructure> innerStructurePool;

  private String header;

  private TCharArrayList originalSequence;
  private TCharArrayList originalStructure;

  private TCharArrayList stemLoopSequence;

  private TCharArrayList danglingLeft;

  private TCharArrayList danglingRight;

  private TCharArrayList backbone;

  StemStructureShuffleData shuffleInformation;

  /**
   * Holds information on the inner structure in a manner that allows lookup by position in the
   * backbone
   */
  private TIntObjectHashMap<InnerStructure> innerStructureMap;

  private static final StemStructureAlphabet structureAlphabet = StemStructureAlphabet
      .getInstance();

  static {
    innerStructurePool = new Pool<InnerStructure>();
  }

  public StemStructure(String sequence, String structure) {
    this(null, sequence, structure);
  }

  public StemStructure(String header, String sequence, String structure) {
    innerStructureMap = new TIntObjectHashMap<InnerStructure>();

    init(header, new TCharArrayList(sequence.toCharArray()),
        new TCharArrayList(structure.toCharArray()));
  }

  public StemStructure(CharBuffer sequence, CharBuffer structure) {
    this(null, sequence, structure);
  }

  public StemStructure(TCharArrayList seq, TCharArrayList str) {
    this(null, seq, str);
  }

  public StemStructure(String header, TCharArrayList seq, TCharArrayList str) {
    innerStructureMap = new TIntObjectHashMap<InnerStructure>();
    init(header, seq, str);
  }

  public StemStructure(String header, CharBuffer sequence, CharBuffer structure) {
    innerStructureMap = new TIntObjectHashMap<InnerStructure>();
    init(header, charBuffer2List(sequence), charBuffer2List(structure));
  }

  private TCharArrayList charBuffer2List(CharBuffer cb) {
    TCharArrayList lst = new TCharArrayList();
    for (int i = 0; i < cb.length(); i++) {
      lst.add(cb.charAt(i));
    }
    return lst;
  }

  private void init(String header, TCharArrayList sequence, TCharArrayList structure) {

    this.header = header;
    if (this.originalSequence == null) {
      this.originalSequence = new TCharArrayList();
      this.originalStructure = new TCharArrayList();
    } else {
      this.originalSequence.resetQuick();
      this.originalStructure.resetQuick();
    }
    for (int i = 0; i < sequence.size(); i++) {
      this.originalSequence.add(sequence.getQuick(i));
      this.originalStructure.add(structure.getQuick(i));
    }
    this.innerStructureMap.clear();

    // init only if needed
    if (this.backbone != null) {
      this.backbone.resetQuick();
      this.stemLoopSequence.resetQuick();
      this.danglingLeft.resetQuick();
      this.danglingRight.resetQuick();
    } else {
      this.backbone = new TCharArrayList();
      this.stemLoopSequence = new TCharArrayList();
      this.danglingLeft = new TCharArrayList();
      this.danglingRight = new TCharArrayList();
    }

    // get the root information
    final int rootStart = structure.lastIndexOf('(') + 1;
    final int rootEnd = structure.indexOf(rootStart, ')') - 1;
    final int loopSize = rootEnd - rootStart + 1;

    // create new root only if needed
    for (int i = 0; i < loopSize; i++) {
      stemLoopSequence.add(sequence.get(i + rootStart));
    }

    // get the backbone and inner structures
    int leftIndex = rootStart - 1;
    int rightIndex = rootEnd + 1;

    final int endDanglingLeft = structure.indexOf('(');
    final int startDanglingRight = structure.lastIndexOf(')') + 1;

    while (leftIndex >= endDanglingLeft && rightIndex <= startDanglingRight) {
      // if both are a pair - into backbone
      char leftChar = '(';
      char rightChar = ')';
      try {
        leftChar = structure.get(leftIndex);
        rightChar = structure.get(rightIndex);
      } catch (Throwable e) {
        System.out.println(sequence);
        System.out.println(structure);
      }

      if (leftChar == '(' && rightChar == ')') {
        this.backbone.add(structureAlphabet.map(sequence.get(leftIndex), sequence.get(rightIndex)));

        leftIndex--;
        rightIndex++;

      } else if (leftChar == '.' && rightChar == '.') {
        // both are dots - inner loop
        InnerStructure in = allocateInnerStructure();

        while (structure.get(leftIndex) != '(') {
          in.appeandLeft(sequence.get(leftIndex));
          leftIndex--;
        }

        while (structure.get(rightIndex) != ')') {
          in.appeandRight(sequence.get(rightIndex));
          rightIndex++;
        }

        innerStructureMap.put(backbone.size(), in);
        this.backbone.add(StemStructureAlphabet.INNER_LOOP);

      } else if (leftChar == '.') {
        // left bulge

        InnerStructure in = allocateInnerStructure();

        while (structure.get(leftIndex) != '(') {
          in.appeandLeft(sequence.get(leftIndex));
          leftIndex--;
        }

        innerStructureMap.put(backbone.size(), in);

        this.backbone.add(StemStructureAlphabet.BULDGE_LEFT);

      } else {
        // right bulge
        InnerStructure in = allocateInnerStructure();

        while (structure.get(rightIndex) != ')') {
          in.appeandRight(sequence.get(rightIndex));
          rightIndex++;
        }
        innerStructureMap.put(backbone.size(), in);

        this.backbone.add(StemStructureAlphabet.BULDGE_RIGHT);
      }
    }
    // handle the dangling edges
    for (int i = 0; i < endDanglingLeft; i++) {
      danglingLeft.add(sequence.get(i));
    }

    final int danglingRightLength = sequence.size() - startDanglingRight;
    for (int i = 0; i < danglingRightLength; i++) {
      danglingRight.add(sequence.get(startDanglingRight + i));
    }

  }

  public void reuse(CharBuffer sequence, CharBuffer structure) {
    reuse(null, sequence, structure);
  }

  public void reuse(String header, CharBuffer sequence, CharBuffer structure) {

    // clear the current map to the cache
    for (int i = 0; i < this.backbone.size(); i++) {
      if (structureAlphabet.isSpecial(this.backbone.get(i))) {
        innerStructurePool.enqueue(innerStructureMap.get(i));
      }
    }
    innerStructureMap.clear();

    init(header, charBuffer2List(sequence), charBuffer2List(structure));
  }

  private InnerStructure allocateInnerStructure() {
    InnerStructure innerStructure = innerStructurePool.dequeue();
    if (innerStructure == null) {
      innerStructure = new InnerStructure();
    } else {
      innerStructure.reset();
    }

    return innerStructure;
  }

  public InnerStructure getInnerStructure(int position) {
    return this.innerStructureMap.get(position);
  }

  public TCharArrayList getStemLoop() {
    return stemLoopSequence;
  }

  public TCharArrayList getBackbone() {
    return backbone;
  }

  /**
   * check if the stem can be shuffled
   *
   * @return return if the stem can be shuffled
   */
  public boolean isShuffleAllowed() {
    return this.shuffleInformation != null;
  }

  /**
   * Remove shuffle capabiliity
   */
  public void disallowShuffle() {
    this.shuffleInformation = null;
  }

  /**
   * Allow shuffle and initiate the appropoate information needed
   */
  public void allowShuffle() {
    this.shuffleInformation = new StemStructureShuffleData();
    this.shuffleInformation.init();
  }

  /**
   * Convert the current Stem to JSON format string
   *
   * @return the JSON string representation of the current structure
   */
  public String toJSON() {
    StringBuilder builder = new StringBuilder();
    String[] data = this.toVienna();
    builder.append("{\"header\":\"");
    builder.append(this.header);
    builder.append('\"');
    builder.append(",\"sequence\":\"");
    builder.append(data[0]);
    builder.append("\",\"structure\":\"");
    builder.append(data[1]);
    builder.append("\"}");
    return builder.toString();
  }

  /**
   *
   * This method return the Vienna format representation of the current information stored in the
   * Stem Structure. this information is returned based on the <b>current</b> information and not
   * the original information provided when built.
   *
   * @return An array of size 2, the first element is the sequence and the second the structure
   */
  public String[] toVienna() {
    StringBuilder sbLeftSequence = new StringBuilder();
    StringBuilder sbRightSequence = new StringBuilder();
    StringBuilder sbLeftStructure = new StringBuilder();
    StringBuilder sbRightStructure = new StringBuilder();

    for (int i = 0; i < this.backbone.size(); i++) {
      if (structureAlphabet.isSpecial(this.backbone.get(i))) {
        /*
         * in case of a inner structure add the information according to each sequence
         */
        InnerStructure in = innerStructureMap.get(i);
        TCharArrayList left = in.getSequenceLeft();
        for (int l = 0; l < left.size(); l++) {
          sbLeftSequence.append(left.get(l));
          sbLeftStructure.append('.');
        }
        TCharArrayList right = in.getSequenceRight();
        for (int r = 0; r < right.size(); r++) {
          sbRightSequence.append(right.get(r));
          sbRightStructure.append('.');
        }
      } else {
        /* in case of a pair add the information directly */
        char[] pair = structureAlphabet.decodePair(this.backbone.get(i));
        sbLeftSequence.append(pair[0]);
        sbLeftStructure.append('(');
        sbRightSequence.append(pair[1]);
        sbRightStructure.append(')');
      }
    }
    // build the sequence
    StringBuilder sbSequence = new StringBuilder();
    addToBuilder(danglingLeft, sbSequence);
    sbLeftSequence.reverse();
    sbSequence.append(sbLeftSequence);
    addToBuilder(stemLoopSequence, sbSequence);
    sbSequence.append(sbRightSequence);
    addToBuilder(danglingRight, sbSequence);

    StringBuilder sbStructure = new StringBuilder();
    addToBuilderDots(danglingLeft, sbStructure);
    sbLeftStructure.reverse();
    sbStructure.append(sbLeftStructure);
    addToBuilderDots(stemLoopSequence, sbStructure);
    sbStructure.append(sbRightStructure);
    addToBuilderDots(danglingRight, sbStructure);

    return new String[] {sbSequence.toString(), sbStructure.toString()};
  }

  /**
   * Help function for format conversion.
   *
   * @param list the characters to write in the builder
   * @param sb the builder into which we write the information
   */
  private void addToBuilder(TCharArrayList list, StringBuilder sb) {
    for (int i = 0; i < list.size(); i++) {
      sb.append(list.get(i));
    }
  }

  /**
   * Help function for format conversion. This method adds '.' as long as the given list size
   *
   * @param list the number of characters to write in the builder
   * @param sb the builder into which we write the dots
   */
  private void addToBuilderDots(TCharArrayList list, StringBuilder sb) {
    for (int i = 0; i < list.size(); i++) {
      sb.append('.');
    }
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append(originalSequence);
    builder.append('\n');
    builder.append(originalStructure);
    return builder.toString();
  }

  /**
   * @return the Header sequence provided
   */
  public final String getHeader() {
    return header;
  }

  /**
   * Get the original sequence
   *
   * @return A representation of the original sequence
   */
  public TCharArrayList getOriginalSequence() {
    return originalSequence;
  }

  /**
   * Get the original Structure
   *
   * @return A representation of the original structure
   */
  public TCharArrayList getOriginalStructure() {
    return originalStructure;
  }

  /**
   * @return the dangling sequence on the left
   */
  public TCharArrayList getDanglingLeft() {
    return danglingLeft;
  }

  /**
   * @return the dangling sequence on the right
   */
  public TCharArrayList getDanglingRight() {
    return danglingRight;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;

    if (obj == null)
      return false;

    if (!(obj instanceof StemStructure))
      return false;

    StemStructure other = (StemStructure) obj;

    if (!backbone.equals(other.backbone)) {
      return false;
    }

    if (header == null) {
      if (other.header != null)
        return false;
    } else if (!header.equals(other.header))
      return false;

    if (innerStructureMap == null) {
      if (other.innerStructureMap != null)
        return false;
    } else if (!innerStructureMap.equals(other.innerStructureMap))
      return false;

    if (originalSequence == null) {
      if (other.originalSequence != null)
        return false;
    } else if (!originalSequence.equals(other.originalSequence))
      return false;

    if (!this.stemLoopSequence.equals(other.stemLoopSequence)) {
      return false;
    }

    if (originalStructure == null) {
      if (other.originalStructure != null)
        return false;
    } else if (!originalStructure.equals(other.originalStructure))
      return false;

    return true;
  }

  public String toSVG() {
    if (100 != 1) {
      throw new UnsupportedOperationException("Not implemented completly");
    }
    StringBuilder sb = new StringBuilder();
    sb.append("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" height=\"100%\" width=\"100%\">\n");

    int y = 100;
    int startX = 10;
    for (int i = 0; i < this.backbone.size(); i++) {
      int pos = startX + i * 50;
      char[] temp = structureAlphabet.decodePair(backbone.get(i));
      String data = temp[0] + "|" + temp[1];
      sb.append("<text id='backbone-" + i + "' x=\"" + pos + "\" y=\"" + y + "\" fill=\"red\">"
          + data + "</text>\n");
      if (structureAlphabet.isSpecial(backbone.get(i))) {
        // this should be fixed
        InnerStructure in = this.innerStructureMap.get(i);
        sb.append(i);
        sb.append(" [label=\"");
        sb.append(in.getSequenceLeft());
        sb.append(':');
        sb.append(in.getSequenceRight());
        sb.append("\"];");
      }
    }

    sb.append("</svg>");

    return sb.toString();
  }

  public String getStringForPosition(int i) {
    StringBuilder sb = new StringBuilder();
    if (structureAlphabet.isSpecial(backbone.get(i))) {
      InnerStructure temp = this.innerStructureMap.get(i);

      sb.append(temp.getSequenceLeft());
      sb.append(':');
      sb.append(temp.getSequenceRight());

    } else {
      char[] temp = structureAlphabet.decodePair(backbone.get(i));

      sb.append(temp[0]);
      sb.append('|');
      sb.append(temp[1]);

    }
    return sb.toString();
  }

  public static ArrayList<StemStructure> readFromFile(String filename) {
    ArrayList<StemStructure> list = new ArrayList<StemStructure>();
    try {
      FileReader file = new FileReader(new File(filename));
      BufferedReader reader = new BufferedReader(file);

      String header = reader.readLine();
      String line1, line2;

      while (header != null) {
        line1 = reader.readLine();
        line2 = reader.readLine();

        list.add(new StemStructure(header.substring(1), new CharBuffer(line1),
            new CharBuffer(line2)));

        header = reader.readLine();

      }
      reader.close();
    } catch (Exception e) {
      list = null;
    }
    return list;
  }

  class StemStructureShuffleData {
    /**
     * Hold the information on the amount of stackings in the <b>original</b>
     * {@link #StemStructure()}. The order is from the loop sequence to the outside
     */
    TIntArrayList stackingLengths;
    /**
     * Counts the number of characters in each sides of the original structure
     */
    private ArrayList<IntPair> counters;
    /**
     * Count the number of un-paired bases in the structure. It is the sum of bases in the dangling
     * ends + the loop sequence + the bulges sequences.
     */
    private int sumOfChararcters;

    public StemStructureShuffleData() {
      stackingLengths = new TIntArrayList();
    }

    public void init() {
      sumOfChararcters = 0;
      // left counters
      TIntArrayList loopCounters = new TIntArrayList();
      // add dangling left counters
      loopCounters.add(danglingLeft.size());
      sumOfChararcters += danglingLeft.size();
      for (int i = 0; i < backbone.size(); i++) {
        if (structureAlphabet.isSpecial(backbone.get(i))) {
          int val = innerStructureMap.get(i).getSequenceLeft().size();
          loopCounters.add(val);
          sumOfChararcters += val;
        }
      }
      // add stem loop length
      loopCounters.add(stemLoopSequence.size());
      sumOfChararcters += stemLoopSequence.size();

      // add dangling right counters
      for (int i = 0; i < backbone.size(); i++) {
        if (structureAlphabet.isSpecial(backbone.get(i))) {
          int val = innerStructureMap.get(i).getSequenceRight().size();
          loopCounters.add(val);
          sumOfChararcters += val;
        }
      }

      loopCounters.add(danglingRight.size());
      sumOfChararcters += danglingRight.size();

      // move the information to a list and sort by size
      counters = new ArrayList<IntPair>();
      for (int i = 0; i < loopCounters.size(); i++) {
        counters.add(new IntPair(i, loopCounters.get(i)));
      }
      Collections.sort(counters, new Comparator<IntPair>() {

        @Override
        public int compare(IntPair o1, IntPair o2) {
          return o2.getSecond() - o1.getSecond();
        }
      });

      // count stackings
      int countFromLastInnerStrcuture = 0;
      for (int i = 0; i < backbone.size(); i++) {
        if (structureAlphabet.isSpecial(backbone.get(i))) {
          stackingLengths.add(countFromLastInnerStrcuture);
          countFromLastInnerStrcuture = 0;
        } else {
          countFromLastInnerStrcuture++;
        }
      }
      stackingLengths.add(countFromLastInnerStrcuture);

    }

  }
}
TOP

Related Classes of bgu.bio.ds.rna.StemStructure$StemStructureShuffleData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.