header updated
[jalview.git] / src / jalview / datamodel / CigarArray.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 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 extends CigarBase\r
22 {\r
23     /**\r
24      * Do CIGAR operations on a set of sequences from many other cigars\r
25      * BAD THINGS WILL HAPPEN IF A CIGARARRAY IS PASSED TO A CIGARARRAY\r
26      * or a CIGARCIGAR is given a CIGARARRAY to insert gaps into.\r
27      */\r
28     /**\r
29      * array of subject cigars\r
30      */\r
31     public CigarSimple refCigars[]=null;\r
32     private boolean seqcigararray=false;\r
33   private CigarArray() {\r
34     super();\r
35   }\r
36 \r
37   /**\r
38    * isSeqCigarArray()\r
39    * @return boolean true if all refCigars resolve to a SeqCigar or a CigarCigar\r
40    */\r
41   public boolean isSeqCigarArray()\r
42   {\r
43     return seqcigararray;\r
44   }\r
45   /**\r
46    * Apply CIGAR operations to several cigars in parallel\r
47    * will throw an error if any of cigar are actually CigarArrays.\r
48    * @param cigar Cigar[]\r
49    */\r
50   public CigarArray(CigarSimple[] cigars) {\r
51     super();\r
52     seqcigararray = true;\r
53     if (cigars != null && cigars.length > 0)\r
54     {\r
55       refCigars = new CigarSimple[cigars.length];\r
56       for (int c = 0; c < cigars.length; c++)\r
57       {\r
58         refCigars[c] = cigars[c];\r
59         if (! ( (cigars[c] instanceof SeqCigar)\r
60                || cigars[c] instanceof CigarCigar))\r
61         {\r
62           seqcigararray = false;\r
63         }\r
64       }\r
65     }\r
66   }\r
67   /**\r
68    * @see Cigar.getSequenceAndDeletions\r
69    * @param GapChar char\r
70    * @return Object[][]\r
71    */\r
72   protected Object[][] getArrayofSequenceAndDeletions(char GapChar) {\r
73       if (refCigars == null || refCigars.length == 0 || length == 0) {\r
74         return null;\r
75       }\r
76       Object[][] sqanddels = new Object[refCigars.length][];\r
77       for (int c=0; c<refCigars.length; c++) {\r
78         String refString = refCigars[c].getSequenceString(GapChar);\r
79         if (refString != null)\r
80         {\r
81           sqanddels[c] = getSequenceAndDeletions(refString, GapChar);\r
82         } else {\r
83           sqanddels[c] = null;\r
84         }\r
85       }\r
86       return sqanddels;\r
87     }\r
88   /**\r
89    * NOTE: this is an improper sequence string function\r
90    * @return String formed by newline concatenated results of applying CIGAR operations to each reference object in turn.\r
91    * @param GapChar char\r
92    * @return '\n' separated strings (empty results included as \n\n)\r
93    */\r
94   public String getSequenceString(char GapChar)\r
95   {\r
96     if (length==0 || refCigars==null)\r
97       return "";\r
98     StringBuffer seqStrings = new StringBuffer();\r
99     Object[][] sqanddels = getArrayofSequenceAndDeletions(GapChar);\r
100     for (int c=0; c<refCigars.length; c++) {\r
101       if (sqanddels[c]!=null) {\r
102         seqStrings.append( (String) sqanddels[c][0]);\r
103         sqanddels[c][0] = null;\r
104       }\r
105       seqStrings.append('\n');\r
106     }\r
107     return seqStrings.toString();\r
108   }\r
109   /**\r
110    * return string results of applying cigar string to all reference cigars\r
111    * @param GapChar char\r
112    * @return String[]\r
113    */\r
114   public String[] getSequenceStrings(char GapChar) {\r
115 \r
116     if (length==0 || refCigars==null || refCigars.length==0)\r
117       return null;\r
118     Object[][] sqanddels = getArrayofSequenceAndDeletions(GapChar);\r
119     String[] seqs = new String[sqanddels.length];\r
120     for (int c=0; c<refCigars.length; c++) {\r
121       seqs[c] = (String) sqanddels[c][0];\r
122     }\r
123     return seqs;\r
124   }\r
125   /**\r
126    * Combines the CigarArray cigar operations with the operations in each\r
127    * reference cigar - creating a new reference cigar\r
128    * @return Cigar[]\r
129 \r
130   public CigarBase[] getEditedCigars() {\r
131 \r
132     return new CigarBase[] {};\r
133   }\r
134 */\r
135   /**\r
136    * applyDeletions\r
137    * edits underlying refCigars to propagate deleted regions, and removes deletion\r
138    * operations from CigarArray operation list.\r
139    * @return int[] position after deletion occured and range of deletion in cigarArray or null if none occured\r
140    */\r
141   public int[] applyDeletions()\r
142   {\r
143     java.util.Vector delpos=null;\r
144     if (length==0)\r
145       return null;\r
146     int cursor=0; // range counter for deletions\r
147     int vcursor=0; // visible column index\r
148     int offset=0; // shift in visible column index as deletions are made\r
149     int i=0;\r
150     while (i<length) {\r
151       if (operation[i]!=D) {\r
152         if (operation[i]==M)\r
153           cursor+=range[i];\r
154         vcursor+=range[i++];\r
155       }\r
156       else\r
157       {\r
158         if (delpos==null)\r
159           delpos=new java.util.Vector();\r
160         int delstart=cursor, delend=cursor+range[i]-1; // inclusive\r
161         delpos.addElement(new int[] { vcursor+offset, range[i]}); // index of right hand column after hidden region boundary\r
162         offset+=range[i]-1; // shift in visible column coordinates\r
163         System.arraycopy(operation, i+1, operation, i, length-i);\r
164         System.arraycopy(range, i+1, range, i, length-i);\r
165         length--;\r
166         /*        int dmax=0;\r
167          for (int s=0; s<refCigars.length; s++) {\r
168            int d = refCigars[s].deleteRange(delstart, delend);\r
169            if (d>dmax)\r
170              dmax=d;\r
171          }\r
172          offset+=dmax; // shift in visible column coordinates\r
173          */\r
174         for (int s=0; s<refCigars.length; s++) {\r
175           int d = refCigars[s].deleteRange(delstart, delend);\r
176         }\r
177 \r
178       }\r
179     }\r
180     if (delpos!=null)\r
181     {\r
182       int[] pos=new int[delpos.size()*2];\r
183       for (int k = 0, l = delpos.size(); k < l; k++) {\r
184         int[] dr = ((int[]) delpos.elementAt(k));\r
185         pos[k*2] = dr[0];\r
186         pos[k*2+1] = dr[1];\r
187         delpos.setElementAt(null,k);\r
188       }\r
189       delpos=null;\r
190       return pos;\r
191     }\r
192     return null;\r
193   }\r
194   /**\r
195    *\r
196    * @return SeqCigar[] or null if CigarArray is not a SeqCigarArray (ie it does not resolve to set of seqCigars)\r
197    */\r
198   public SeqCigar[] getSeqCigarArray() {\r
199     if (!isSeqCigarArray())\r
200       return null;\r
201     SeqCigar[] sa = new SeqCigar[refCigars.length];\r
202     for (int i=0; i<refCigars.length; i++)\r
203       sa[i] = (SeqCigar) refCigars[i];\r
204     return sa;\r
205   }\r
206 }\r