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