d4d06eeb8d91574f69064e504b9a26339bc1e2a5
[jalview.git] / src / jalview / util / ShiftList.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.util;
19
20 import java.util.*;
21
22 /**
23  * ShiftList Simple way of mapping a linear series to a new linear range with
24  * new points introduced. Use at your own risk! Now growing to be used for
25  * interval ranges (position, offset) storing deletions/insertions
26  */
27 public class ShiftList
28 {
29   public Vector shifts;
30
31   public ShiftList()
32   {
33     shifts = new Vector();
34   }
35
36   /**
37    * addShift
38    * 
39    * @param pos
40    *          start position for shift (in original reference frame)
41    * @param shift
42    *          length of shift
43    */
44   public void addShift(int pos, int shift)
45   {
46     int sidx = 0;
47     int[] rshift = null;
48     while (sidx < shifts.size()
49             && (rshift = (int[]) shifts.elementAt(sidx))[0] < pos)
50     {
51       sidx++;
52     }
53     if (sidx == shifts.size())
54     {
55       shifts.insertElementAt(new int[]
56       { pos, shift }, sidx);
57     }
58     else
59     {
60       rshift[1] += shift;
61     }
62   }
63
64   /**
65    * shift
66    * 
67    * @param pos
68    *          int
69    * @return int shifted position
70    */
71   public int shift(int pos)
72   {
73     if (shifts.size() == 0)
74     {
75       return pos;
76     }
77     int shifted = pos;
78     int sidx = 0;
79     int rshift[];
80     while (sidx < shifts.size()
81             && (rshift = ((int[]) shifts.elementAt(sidx++)))[0] <= pos)
82     {
83       shifted += rshift[1];
84     }
85     return shifted;
86   }
87
88   /**
89    * clear all shifts
90    */
91   public void clear()
92   {
93     shifts.removeAllElements();
94   }
95
96   /**
97    * invert the shifts
98    * 
99    * @return ShiftList with inverse shift operations
100    */
101   public ShiftList getInverse()
102   {
103     ShiftList inverse = new ShiftList();
104     if (shifts != null)
105     {
106       for (int i = 0, j = shifts.size(); i < j; i++)
107       {
108         int[] sh = (int[]) shifts.elementAt(i);
109         if (sh != null)
110         {
111           inverse.shifts.addElement(new int[]
112           { sh[0], -sh[1] });
113         }
114       }
115     }
116     return inverse;
117   }
118
119   /**
120    * parse a 1d map of position 1<i<n to L<pos[i]<N such as that returned from
121    * SequenceI.gapMap()
122    * 
123    * @param gapMap
124    * @return shifts from map index to mapped position
125    */
126   public static ShiftList parseMap(int[] gapMap)
127   {
128     ShiftList shiftList = null;
129     if (gapMap != null && gapMap.length > 0)
130     {
131       shiftList = new ShiftList();
132       for (int i = 0, p = 0; i < gapMap.length; p++, i++)
133       {
134         if (p != gapMap[i])
135         {
136           shiftList.addShift(p, gapMap[i] - p);
137           p = gapMap[i];
138         }
139       }
140     }
141     return shiftList;
142   }
143 }