2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
\r
3 * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
\r
5 * This file is part of Jalview.
\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
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
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
18 package jalview.datamodel;
\r
20 import java.util.Vector;
\r
22 public class CigarArray extends CigarBase
\r
25 * Do CIGAR operations on a set of sequences from many other cigars BAD THINGS
\r
26 * WILL HAPPEN IF A CIGARARRAY IS PASSED TO A CIGARARRAY or a CIGARCIGAR is
\r
27 * given a CIGARARRAY to insert gaps into.
\r
30 * array of subject cigars
\r
32 public CigarSimple refCigars[] = null;
\r
34 private boolean seqcigararray = false;
\r
36 private CigarArray()
\r
44 * @return boolean true if all refCigars resolve to a SeqCigar or a CigarCigar
\r
46 public boolean isSeqCigarArray()
\r
48 return seqcigararray;
\r
52 * Apply CIGAR operations to several cigars in parallel will throw an error if
\r
53 * any of cigar are actually CigarArrays.
\r
58 public CigarArray(CigarSimple[] cigars)
\r
61 seqcigararray = true;
\r
62 if (cigars != null && cigars.length > 0)
\r
64 refCigars = new CigarSimple[cigars.length];
\r
65 for (int c = 0; c < cigars.length; c++)
\r
67 refCigars[c] = cigars[c];
\r
68 if (!((cigars[c] instanceof SeqCigar) || cigars[c] instanceof CigarCigar))
\r
70 seqcigararray = false;
\r
77 * construct a cigar array from the current alignment, or just the subset of the current alignment specified by selectionGroup. Any columns marked as hidden in columnSelection will be marked as deleted in the array.
\r
79 * @param columnSelection
\r
80 * @param selectionGroup
\r
82 public CigarArray(AlignmentI alignment, ColumnSelection columnSelection, SequenceGroup selectionGroup)
\r
84 this(constructSeqCigarArray(alignment, selectionGroup));
\r
85 constructFromAlignment(alignment, columnSelection!=null ? columnSelection.getHiddenColumns() : null, selectionGroup);
\r
87 private static int[] _calcStartEndBounds(AlignmentI alignment, SequenceGroup selectionGroup)
\r
89 int[] startend = new int[] { 0,0,0};
\r
90 if (selectionGroup != null)
\r
92 startend[0] = selectionGroup.getSize();
\r
93 startend[1] = selectionGroup.getStartRes();
\r
94 startend[2] = selectionGroup.getEndRes(); // inclusive for start and end in
\r
95 // SeqCigar constructor
\r
99 startend[0] = alignment.getHeight();
\r
100 startend[2] = alignment.getWidth() - 1;
\r
104 public static SeqCigar[] constructSeqCigarArray(AlignmentI alignment, SequenceGroup selectionGroup)
\r
106 SequenceI[] seqs = null;
\r
108 int _startend[] = _calcStartEndBounds(alignment, selectionGroup);
\r
109 int start = _startend[1],end=_startend[2];
\r
110 if (selectionGroup != null)
\r
112 iSize = selectionGroup.getSize();
\r
113 seqs = selectionGroup.getSequencesInOrder(alignment);
\r
114 start = selectionGroup.getStartRes();
\r
115 end = selectionGroup.getEndRes(); // inclusive for start and end in
\r
116 // SeqCigar constructor
\r
120 iSize = alignment.getHeight();
\r
121 seqs = alignment.getSequencesArray();
\r
122 end = alignment.getWidth() - 1;
\r
124 SeqCigar[] selseqs = new SeqCigar[iSize];
\r
125 for (i = 0; i < iSize; i++)
\r
127 selseqs[i] = new SeqCigar(seqs[i], start, end);
\r
132 * internal constructor function - called by CigarArray(AlignmentI, ...);
\r
134 * @param columnSelection - vector of visible regions as returned from columnSelection.getHiddenColumns()
\r
135 * @param selectionGroup
\r
137 private void constructFromAlignment(AlignmentI alignment, Vector columnSelection, SequenceGroup selectionGroup)
\r
139 int[] _startend = _calcStartEndBounds(alignment, selectionGroup);
\r
140 int start = _startend[1],end=_startend[2];
\r
141 // now construct the CigarArray operations
\r
142 if (columnSelection!=null)
\r
145 int hideStart, hideEnd;
\r
147 for (int j = 0; last < end & j < columnSelection.size(); j++)
\r
149 region = (int[]) columnSelection.elementAt(j);
\r
150 hideStart = region[0];
\r
151 hideEnd = region[1];
\r
152 // edit hidden regions to selection range
\r
153 if (hideStart < last)
\r
155 if (hideEnd > last)
\r
165 if (hideStart > end)
\r
175 if (hideStart > hideEnd)
\r
180 * form operations...
\r
182 if (last < hideStart)
\r
184 addOperation(CigarArray.M, hideStart - last);
\r
186 addOperation(CigarArray.D, 1 + hideEnd - hideStart);
\r
187 last = hideEnd + 1;
\r
189 // Final match if necessary.
\r
192 addOperation(CigarArray.M, end - last + 1);
\r
197 addOperation(CigarArray.M, end - start + 1);
\r
202 * @see Cigar.getSequenceAndDeletions
\r
205 * @return Object[][]
\r
207 protected Object[][] getArrayofSequenceAndDeletions(char GapChar)
\r
209 if (refCigars == null || refCigars.length == 0 || length == 0)
\r
213 Object[][] sqanddels = new Object[refCigars.length][];
\r
214 for (int c = 0; c < refCigars.length; c++)
\r
216 String refString = refCigars[c].getSequenceString(GapChar);
\r
217 if (refString != null)
\r
219 sqanddels[c] = getSequenceAndDeletions(refString, GapChar);
\r
223 sqanddels[c] = null;
\r
230 * NOTE: this is an improper sequence string function
\r
232 * @return String formed by newline concatenated results of applying CIGAR
\r
233 * operations to each reference object in turn.
\r
236 * @return '\n' separated strings (empty results included as \n\n)
\r
238 public String getSequenceString(char GapChar)
\r
240 if (length == 0 || refCigars == null)
\r
244 StringBuffer seqStrings = new StringBuffer();
\r
245 Object[][] sqanddels = getArrayofSequenceAndDeletions(GapChar);
\r
246 for (int c = 0; c < refCigars.length; c++)
\r
248 if (sqanddels[c] != null)
\r
250 seqStrings.append((String) sqanddels[c][0]);
\r
251 sqanddels[c][0] = null;
\r
253 seqStrings.append('\n');
\r
255 return seqStrings.toString();
\r
259 * return string results of applying cigar string to all reference cigars
\r
265 public String[] getSequenceStrings(char GapChar)
\r
268 if (length == 0 || refCigars == null || refCigars.length == 0)
\r
272 Object[][] sqanddels = getArrayofSequenceAndDeletions(GapChar);
\r
273 String[] seqs = new String[sqanddels.length];
\r
274 for (int c = 0; c < refCigars.length; c++)
\r
276 seqs[c] = (String) sqanddels[c][0];
\r
282 * Combines the CigarArray cigar operations with the operations in each
\r
283 * reference cigar - creating a new reference cigar
\r
287 * public CigarBase[] getEditedCigars() {
\r
289 * return new CigarBase[] {}; }
\r
292 * applyDeletions edits underlying refCigars to propagate deleted regions, and
\r
293 * removes deletion operations from CigarArray operation list.
\r
295 * @return int[] position after deletion occured and range of deletion in
\r
296 * cigarArray or null if none occured
\r
298 public int[] applyDeletions()
\r
300 java.util.Vector delpos = null;
\r
305 int cursor = 0; // range counter for deletions
\r
306 int vcursor = 0; // visible column index
\r
307 int offset = 0; // shift in visible column index as deletions are made
\r
311 if (operation[i] != D)
\r
313 if (operation[i] == M)
\r
315 cursor += range[i];
\r
317 vcursor += range[i++];
\r
321 if (delpos == null)
\r
323 delpos = new java.util.Vector();
\r
325 int delstart = cursor, delend = cursor + range[i] - 1; // inclusive
\r
326 delpos.addElement(new int[]
\r
327 { vcursor + offset, range[i] }); // index of right hand column after
\r
328 // hidden region boundary
\r
329 offset += range[i] - 1; // shift in visible column coordinates
\r
330 System.arraycopy(operation, i + 1, operation, i, length - i);
\r
331 System.arraycopy(range, i + 1, range, i, length - i);
\r
334 * int dmax=0; for (int s=0; s<refCigars.length; s++) { int d =
\r
335 * refCigars[s].deleteRange(delstart, delend); if (d>dmax) dmax=d; }
\r
336 * offset+=dmax; // shift in visible column coordinates
\r
338 for (int s = 0; s < refCigars.length; s++)
\r
340 int d = refCigars[s].deleteRange(delstart, delend);
\r
345 if (delpos != null)
\r
347 int[] pos = new int[delpos.size() * 2];
\r
348 for (int k = 0, l = delpos.size(); k < l; k++)
\r
350 int[] dr = ((int[]) delpos.elementAt(k));
\r
351 pos[k * 2] = dr[0];
\r
352 pos[k * 2 + 1] = dr[1];
\r
353 delpos.setElementAt(null, k);
\r
363 * @return SeqCigar[] or null if CigarArray is not a SeqCigarArray (ie it does
\r
364 * not resolve to set of seqCigars)
\r
366 public SeqCigar[] getSeqCigarArray()
\r
368 if (!isSeqCigarArray())
\r
372 SeqCigar[] sa = new SeqCigar[refCigars.length];
\r
373 for (int i = 0; i < refCigars.length; i++)
\r
375 sa[i] = (SeqCigar) refCigars[i];
\r