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