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