Formatting
[jalview.git] / src / jalview / datamodel / CigarArray.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.datamodel;\r
20 \r
21 public class CigarArray\r
22     extends CigarBase\r
23 {\r
24   /**\r
25    * Do CIGAR operations on a set of sequences from many other cigars\r
26    * BAD THINGS WILL HAPPEN IF A CIGARARRAY IS PASSED TO A CIGARARRAY\r
27    * or a CIGARCIGAR is given a CIGARARRAY to insert gaps into.\r
28    */\r
29   /**\r
30    * array of subject cigars\r
31    */\r
32   public CigarSimple refCigars[] = null;\r
33   private boolean seqcigararray = false;\r
34   private CigarArray()\r
35   {\r
36     super();\r
37   }\r
38 \r
39   /**\r
40    * isSeqCigarArray()\r
41    * @return boolean true if all refCigars resolve to a SeqCigar or a CigarCigar\r
42    */\r
43   public boolean isSeqCigarArray()\r
44   {\r
45     return seqcigararray;\r
46   }\r
47 \r
48   /**\r
49    * Apply CIGAR operations to several cigars in parallel\r
50    * will throw an error if any of cigar are actually CigarArrays.\r
51    * @param cigar Cigar[]\r
52    */\r
53   public CigarArray(CigarSimple[] cigars)\r
54   {\r
55     super();\r
56     seqcigararray = true;\r
57     if (cigars != null && cigars.length > 0)\r
58     {\r
59       refCigars = new CigarSimple[cigars.length];\r
60       for (int c = 0; c < cigars.length; c++)\r
61       {\r
62         refCigars[c] = cigars[c];\r
63         if (! ( (cigars[c] instanceof SeqCigar)\r
64                || cigars[c] instanceof CigarCigar))\r
65         {\r
66           seqcigararray = false;\r
67         }\r
68       }\r
69     }\r
70   }\r
71 \r
72   /**\r
73    * @see Cigar.getSequenceAndDeletions\r
74    * @param GapChar char\r
75    * @return Object[][]\r
76    */\r
77   protected Object[][] getArrayofSequenceAndDeletions(char GapChar)\r
78   {\r
79     if (refCigars == null || refCigars.length == 0 || length == 0)\r
80     {\r
81       return null;\r
82     }\r
83     Object[][] sqanddels = new Object[refCigars.length][];\r
84     for (int c = 0; c < refCigars.length; c++)\r
85     {\r
86       String refString = refCigars[c].getSequenceString(GapChar);\r
87       if (refString != null)\r
88       {\r
89         sqanddels[c] = getSequenceAndDeletions(refString, GapChar);\r
90       }\r
91       else\r
92       {\r
93         sqanddels[c] = null;\r
94       }\r
95     }\r
96     return sqanddels;\r
97   }\r
98 \r
99   /**\r
100    * NOTE: this is an improper sequence string function\r
101    * @return String formed by newline concatenated results of applying CIGAR operations to each reference object in turn.\r
102    * @param GapChar char\r
103    * @return '\n' separated strings (empty results included as \n\n)\r
104    */\r
105   public String getSequenceString(char GapChar)\r
106   {\r
107     if (length == 0 || refCigars == null)\r
108     {\r
109       return "";\r
110     }\r
111     StringBuffer seqStrings = new StringBuffer();\r
112     Object[][] sqanddels = getArrayofSequenceAndDeletions(GapChar);\r
113     for (int c = 0; c < refCigars.length; c++)\r
114     {\r
115       if (sqanddels[c] != null)\r
116       {\r
117         seqStrings.append( (String) sqanddels[c][0]);\r
118         sqanddels[c][0] = null;\r
119       }\r
120       seqStrings.append('\n');\r
121     }\r
122     return seqStrings.toString();\r
123   }\r
124 \r
125   /**\r
126    * return string results of applying cigar string to all reference cigars\r
127    * @param GapChar char\r
128    * @return String[]\r
129    */\r
130   public String[] getSequenceStrings(char GapChar)\r
131   {\r
132 \r
133     if (length == 0 || refCigars == null || refCigars.length == 0)\r
134     {\r
135       return null;\r
136     }\r
137     Object[][] sqanddels = getArrayofSequenceAndDeletions(GapChar);\r
138     String[] seqs = new String[sqanddels.length];\r
139     for (int c = 0; c < refCigars.length; c++)\r
140     {\r
141       seqs[c] = (String) sqanddels[c][0];\r
142     }\r
143     return seqs;\r
144   }\r
145 \r
146   /**\r
147    * Combines the CigarArray cigar operations with the operations in each\r
148    * reference cigar - creating a new reference cigar\r
149    * @return Cigar[]\r
150 \r
151      public CigarBase[] getEditedCigars() {\r
152 \r
153     return new CigarBase[] {};\r
154      }\r
155    */\r
156   /**\r
157    * applyDeletions\r
158    * edits underlying refCigars to propagate deleted regions, and removes deletion\r
159    * operations from CigarArray operation list.\r
160    * @return int[] position after deletion occured and range of deletion in cigarArray or null if none occured\r
161    */\r
162   public int[] applyDeletions()\r
163   {\r
164     java.util.Vector delpos = null;\r
165     if (length == 0)\r
166     {\r
167       return null;\r
168     }\r
169     int cursor = 0; // range counter for deletions\r
170     int vcursor = 0; // visible column index\r
171     int offset = 0; // shift in visible column index as deletions are made\r
172     int i = 0;\r
173     while (i < length)\r
174     {\r
175       if (operation[i] != D)\r
176       {\r
177         if (operation[i] == M)\r
178         {\r
179           cursor += range[i];\r
180         }\r
181         vcursor += range[i++];\r
182       }\r
183       else\r
184       {\r
185         if (delpos == null)\r
186         {\r
187           delpos = new java.util.Vector();\r
188         }\r
189         int delstart = cursor, delend = cursor + range[i] - 1; // inclusive\r
190         delpos.addElement(new int[]\r
191                           {vcursor + offset, range[i]}); // index of right hand column after hidden region boundary\r
192         offset += range[i] - 1; // shift in visible column coordinates\r
193         System.arraycopy(operation, i + 1, operation, i, length - i);\r
194         System.arraycopy(range, i + 1, range, i, length - i);\r
195         length--;\r
196         /*        int dmax=0;\r
197          for (int s=0; s<refCigars.length; s++) {\r
198            int d = refCigars[s].deleteRange(delstart, delend);\r
199            if (d>dmax)\r
200              dmax=d;\r
201          }\r
202          offset+=dmax; // shift in visible column coordinates\r
203          */\r
204         for (int s = 0; s < refCigars.length; s++)\r
205         {\r
206           int d = refCigars[s].deleteRange(delstart, delend);\r
207         }\r
208 \r
209       }\r
210     }\r
211     if (delpos != null)\r
212     {\r
213       int[] pos = new int[delpos.size() * 2];\r
214       for (int k = 0, l = delpos.size(); k < l; k++)\r
215       {\r
216         int[] dr = ( (int[]) delpos.elementAt(k));\r
217         pos[k * 2] = dr[0];\r
218         pos[k * 2 + 1] = dr[1];\r
219         delpos.setElementAt(null, k);\r
220       }\r
221       delpos = null;\r
222       return pos;\r
223     }\r
224     return null;\r
225   }\r
226 \r
227   /**\r
228    *\r
229    * @return SeqCigar[] or null if CigarArray is not a SeqCigarArray (ie it does not resolve to set of seqCigars)\r
230    */\r
231   public SeqCigar[] getSeqCigarArray()\r
232   {\r
233     if (!isSeqCigarArray())\r
234     {\r
235       return null;\r
236     }\r
237     SeqCigar[] sa = new SeqCigar[refCigars.length];\r
238     for (int i = 0; i < refCigars.length; i++)\r
239     {\r
240       sa[i] = (SeqCigar) refCigars[i];\r
241     }\r
242     return sa;\r
243   }\r
244 }\r