/**
   * @param gas_seq The sequence which we wish to map it against other sequence(s)
   * @param gas_targetSeqs The target sequence
   */
  private HashMap<Integer, Integer> doMapSeq2Seq(
      GappedAlignmentString gas_seq, GappedAlignmentString[] gas_targetSeqs) {
    int N = gas_seq.gappedLength();
    // making map allocation more efficient
    int initCapacity = (int) Math.ceil(1.5 * N);
    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(initCapacity);

    // When a gap position corresponds to a gap remove it from seq
    HashMap<Integer, Integer> gapped2UngappedMap_seq = gas_seq.getGapped2UngappedMap();
    Integer[] gapPositions_seq = gas_seq.determineGapPositions();
    for (Integer e : gapPositions_seq) gapped2UngappedMap_seq.remove(e);

    // When a gap position corresponds to a gap, put -1 as its value
    HashMap<Integer, Integer> gapped2UngappedMap_targetSeq =
        gas_targetSeqs[0].getGapped2UngappedMap();
    Integer[] gapPositions_targetSeq = gas_targetSeqs[0].determineGapPositions();
    for (Integer e : gapPositions_targetSeq) gapped2UngappedMap_targetSeq.put(e, -1);

    Integer[] gappedPositionsNoGaps_seq =
        gapped2UngappedMap_seq.keySet().toArray(new Integer[gapped2UngappedMap_seq.size()]);
    for (Integer gappedPosNoGaps : gappedPositionsNoGaps_seq) {
      Integer ungappedPos = gapped2UngappedMap_targetSeq.get(gappedPosNoGaps);
      if (ungappedPos.equals(null)) {
        ungappedPos = -1;
      }
      map.put(gapped2UngappedMap_seq.get(gappedPosNoGaps), ungappedPos);
    }

    return map;
  } // end of doMapSeq2Seq method
  /**
   * Valid values for <tt>s1</tt> and <tt>s2</tt> are [0, ordering.size()-1]
   *
   * @param s1 The serial number of the sequence (<tt>s1</tt>) whose coordinate we wish to map
   *     against that of (<tt>s2</tt>)
   * @param s2 The other sequence
   * @param ugidx The ungapped coordinate of (<tt>s1</tt>)
   * @return The ungapped coordinate of (<tt>s2</tt>) corresponding to <tt>ugidx</tt>
   * @see GappedAlignmentString
   */
  public int mapUngapped(int s1, int s2, int ugidx) throws IndexOutOfBoundsException {
    if ((s1 < 0 || s1 >= ordering.size()) || (s2 < 0 || s2 >= ordering.size()))
      throw new IndexOutOfBoundsException("Valid values for s1 and s2 are [0, ordering.size()-1]");

    GappedAlignmentString str1 = gappedAlignments.get(ordering.get(s1));
    GappedAlignmentString str2 = gappedAlignments.get(ordering.get(s2));
    int gidx = str1.ungappedToGapped(ugidx);
    int ugidx2 = str2.gappedToUngapped(gidx);
    if (str2.isGap(gidx)) {
      return -1;
    }
    return ugidx2;
  }
 /**
  * Adds the sequence with name <tt>name</tt> and sequence <tt>gas</tt> to the alignment.
  *
  * @param name The name of the sequence to be added
  * @param gas The sequence as a <tt>GappedAlignmentString</tt>
  * @see GappedAlignmentString
  */
 public void addGappedAlignment(String name, GappedAlignmentString gas) {
   if (ordering.isEmpty()) {
     gappedLength = gas.gappedLength();
   } else {
     if (gas.gappedLength() != gappedLength) {
       throw new IllegalArgumentException(
           String.format("Gapped Length %d doesn't match.", gas.gappedLength()));
     }
     if (ordering.contains(name)) {
       throw new IllegalArgumentException(String.format("Duplicate name: %s", name));
     }
   }
   ordering.add(name);
   gappedAlignments.put(name, gas);
 }