Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.io

File AnnotationFile.java

 

Coverage histogram

../../img/srcFileCovDistChart8.png
19% of files have more coverage

Code metrics

434
765
28
2
1,797
1,525
304
0.4
27.32
14
10.86

Classes

Class Line # Actions
AnnotationFile 53 761 303 336
0.725040972.5%
AnnotationFile.ViewDef 112 4 1 0
1.0100%
 

Contributing tests

This file is covered by 8 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.io;
22   
23    import jalview.analysis.Conservation;
24    import jalview.api.AlignViewportI;
25    import jalview.datamodel.AlignmentAnnotation;
26    import jalview.datamodel.AlignmentI;
27    import jalview.datamodel.Annotation;
28    import jalview.datamodel.ColumnSelection;
29    import jalview.datamodel.GraphLine;
30    import jalview.datamodel.HiddenColumns;
31    import jalview.datamodel.HiddenSequences;
32    import jalview.datamodel.SequenceGroup;
33    import jalview.datamodel.SequenceI;
34    import jalview.schemes.ColourSchemeI;
35    import jalview.schemes.ColourSchemeProperty;
36    import jalview.util.ColorUtils;
37   
38    import java.awt.Color;
39    import java.io.BufferedReader;
40    import java.io.FileReader;
41    import java.io.InputStreamReader;
42    import java.io.StringReader;
43    import java.net.URL;
44    import java.util.ArrayList;
45    import java.util.BitSet;
46    import java.util.Enumeration;
47    import java.util.Hashtable;
48    import java.util.List;
49    import java.util.Map;
50    import java.util.StringTokenizer;
51    import java.util.Vector;
52   
 
53    public class AnnotationFile
54    {
 
55  28 toggle public AnnotationFile()
56    {
57  28 init();
58    }
59   
60    /**
61    * character used to write newlines
62    */
63    protected String newline = System.getProperty("line.separator");
64   
65    /**
66    * set new line string and reset the output buffer
67    *
68    * @param nl
69    */
 
70  0 toggle public void setNewlineString(String nl)
71    {
72  0 newline = nl;
73  0 init();
74    }
75   
 
76  0 toggle public String getNewlineString()
77    {
78  0 return newline;
79    }
80   
81    StringBuffer text;
82   
 
83  28 toggle private void init()
84    {
85  28 text = new StringBuffer("JALVIEW_ANNOTATION" + newline + "# Created: "
86    + new java.util.Date() + newline + newline);
87  28 refSeq = null;
88  28 refSeqId = null;
89    }
90   
91    /**
92    * convenience method for pre-2.9 annotation files which have no view, hidden
93    * columns or hidden row keywords.
94    *
95    * @param annotations
96    * @param list
97    * @param properties
98    * @return annotation file as a string.
99    */
 
100  0 toggle public String printAnnotations(AlignmentAnnotation[] annotations,
101    List<SequenceGroup> list, Hashtable properties)
102    {
103  0 return printAnnotations(annotations, list, properties, null, null,
104    null);
105   
106    }
107   
108    /**
109    * hold all the information about a particular view definition read from or
110    * written out in an annotations file.
111    */
 
112    public class ViewDef
113    {
114    // TODO this class is not used - remove?
115    public final String viewname;
116   
117    public final HiddenSequences hidseqs;
118   
119    public final HiddenColumns hiddencols;
120   
121    public final Hashtable hiddenRepSeqs;
122   
 
123  5 toggle public ViewDef(String vname, HiddenSequences hseqs, HiddenColumns hcols,
124    Hashtable hRepSeqs)
125    {
126  5 this.viewname = vname;
127  5 this.hidseqs = hseqs;
128  5 this.hiddencols = hcols;
129  5 this.hiddenRepSeqs = hRepSeqs;
130    }
131    }
132   
133    /**
134    * Prepare an annotation file given a set of annotations, groups, alignment
135    * properties and views.
136    *
137    * @param annotations
138    * @param list
139    * @param properties
140    * @param views
141    * @return annotation file
142    */
 
143  5 toggle public String printAnnotations(AlignmentAnnotation[] annotations,
144    List<SequenceGroup> list, Hashtable properties, HiddenColumns cs,
145    AlignmentI al, ViewDef view)
146    {
147  5 if (view != null)
148    {
149  5 if (view.viewname != null)
150    {
151  0 text.append("VIEW_DEF\t" + view.viewname + "\n");
152    }
153  5 if (list == null)
154    {
155    // list = view.visibleGroups;
156    }
157  5 if (cs == null)
158    {
159  5 cs = view.hiddencols;
160    }
161  5 if (al == null)
162    {
163    // add hidden rep sequences.
164    }
165    }
166    // first target - store and restore all settings for a view.
167  5 if (al != null && al.hasSeqrep())
168    {
169  1 text.append("VIEW_SETREF\t" + al.getSeqrep().getName() + "\n");
170    }
171  5 if (cs != null && cs.hasHiddenColumns())
172    {
173  1 text.append("VIEW_HIDECOLS\t");
174   
175  1 String regions = cs.regionsToString(",", "-");
176  1 text.append(regions);
177  1 text.append("\n");
178    }
179    // TODO: allow efficient recovery of annotation data shown in several
180    // different views
181  5 if (annotations != null)
182    {
183  4 boolean oneColour = true;
184  4 AlignmentAnnotation row;
185  4 String comma;
186  4 SequenceI refSeq = null;
187  4 SequenceGroup refGroup = null;
188   
189  4 StringBuffer colours = new StringBuffer();
190  4 StringBuffer graphLine = new StringBuffer();
191  4 StringBuffer rowprops = new StringBuffer();
192  4 Hashtable<Integer, String> graphGroup = new Hashtable<>();
193  4 Hashtable<Integer, Object[]> graphGroup_refs = new Hashtable<>();
194  4 BitSet graphGroupSeen = new BitSet();
195   
196  4 java.awt.Color color;
197   
198  84 for (int i = 0; i < annotations.length; i++)
199    {
200  80 row = annotations[i];
201   
202  80 if (!row.visible && !row.hasScore() && !(row.graphGroup > -1
203    && graphGroupSeen.get(row.graphGroup)))
204    {
205  0 continue;
206    }
207   
208  80 color = null;
209  80 oneColour = true;
210   
211    // mark any sequence references for the row
212  80 writeSequence_Ref(refSeq, row.sequenceRef);
213  80 refSeq = row.sequenceRef;
214    // mark any group references for the row
215  80 writeGroup_Ref(refGroup, row.groupRef);
216  80 refGroup = row.groupRef;
217   
218  80 boolean hasGlyphs = row.hasIcons, hasLabels = row.hasText,
219    hasValues = row.hasScore, hasText = false;
220    // lookahead to check what the annotation row object actually contains.
221  12348 for (int j = 0; row.annotations != null
222    && j < row.annotations.length
223    && (!hasGlyphs || !hasLabels || !hasValues); j++)
224    {
225  12268 if (row.annotations[j] != null)
226    {
227  9156 hasLabels |= (row.annotations[j].displayCharacter != null
228    && row.annotations[j].displayCharacter.length() > 0
229    && !row.annotations[j].displayCharacter.equals(" "));
230  9156 hasGlyphs |= (row.annotations[j].secondaryStructure != 0
231    && row.annotations[j].secondaryStructure != ' ');
232  9156 hasValues |= (!Float.isNaN(row.annotations[j].value)); // NaNs can't
233    // be
234    // rendered..
235  9156 hasText |= (row.annotations[j].description != null
236    && row.annotations[j].description.length() > 0);
237    }
238    }
239   
240  80 if (row.graph == AlignmentAnnotation.NO_GRAPH)
241    {
242  4 text.append("NO_GRAPH\t");
243  4 hasValues = false; // only secondary structure
244    // hasLabels = false; // and annotation description string.
245    }
246    else
247    {
248  76 if (row.graph == AlignmentAnnotation.BAR_GRAPH)
249    {
250  10 text.append("BAR_GRAPH\t");
251  10 hasGlyphs = false; // no secondary structure
252   
253    }
254  66 else if (row.graph == AlignmentAnnotation.LINE_GRAPH)
255    {
256  66 hasGlyphs = false; // no secondary structure
257  66 text.append("LINE_GRAPH\t");
258    }
259   
260  76 if (row.getThreshold() != null)
261    {
262  62 graphLine.append("GRAPHLINE\t");
263  62 graphLine.append(row.label);
264  62 graphLine.append("\t");
265  62 graphLine.append(row.getThreshold().value);
266  62 graphLine.append("\t");
267  62 graphLine.append(row.getThreshold().label);
268  62 graphLine.append("\t");
269  62 graphLine.append(jalview.util.Format
270    .getHexString(row.getThreshold().colour));
271  62 graphLine.append(newline);
272    }
273   
274  76 if (row.graphGroup > -1)
275    {
276  66 graphGroupSeen.set(row.graphGroup);
277  66 Integer key = new Integer(row.graphGroup);
278  66 if (graphGroup.containsKey(key))
279    {
280  33 graphGroup.put(key, graphGroup.get(key) + "\t" + row.label);
281   
282    }
283    else
284    {
285  33 graphGroup_refs.put(key, new Object[] { refSeq, refGroup });
286  33 graphGroup.put(key, row.label);
287    }
288    }
289    }
290   
291  80 text.append(row.label + "\t");
292  80 if (row.description != null)
293    {
294  68 text.append(row.description + "\t");
295    }
296  12640 for (int j = 0; row.annotations != null
297    && j < row.annotations.length; j++)
298    {
299  12560 if (refSeq != null
300    && jalview.util.Comparison.isGap(refSeq.getCharAt(j)))
301    {
302  1462 continue;
303    }
304   
305  11098 if (row.annotations[j] != null)
306    {
307  9168 comma = "";
308  9168 if (hasGlyphs) // could be also hasGlyphs || ...
309    {
310   
311  32 text.append(comma);
312  32 if (row.annotations[j].secondaryStructure != ' ')
313    {
314    // only write out the field if its not whitespace.
315  32 text.append(row.annotations[j].secondaryStructure);
316    }
317  32 comma = ",";
318    }
319  9168 if (hasValues)
320    {
321  9136 if (!Float.isNaN(row.annotations[j].value))
322    {
323  9136 text.append(comma + row.annotations[j].value);
324    }
325    else
326    {
327    // System.err.println("Skipping NaN - not valid value.");
328  0 text.append(comma + 0f);// row.annotations[j].value);
329    }
330  9136 comma = ",";
331    }
332  9168 if (hasLabels)
333    {
334    // TODO: labels are emitted after values for bar graphs.
335  9150 if // empty labels are allowed, so
336  9150 (row.annotations[j].displayCharacter != null
337    && row.annotations[j].displayCharacter.length() > 0
338    && !row.annotations[j].displayCharacter.equals(" "))
339    {
340  362 text.append(comma + row.annotations[j].displayCharacter);
341  362 comma = ",";
342    }
343    }
344  9168 if (hasText)
345    {
346  9070 if (row.annotations[j].description != null
347    && row.annotations[j].description.length() > 0
348    && !row.annotations[j].description
349    .equals(row.annotations[j].displayCharacter))
350    {
351  9028 text.append(comma + row.annotations[j].description);
352  9028 comma = ",";
353    }
354    }
355  9168 if (color != null && !color.equals(row.annotations[j].colour))
356    {
357  450 oneColour = false;
358    }
359   
360  9168 color = row.annotations[j].colour;
361   
362  9168 if (row.annotations[j].colour != null
363    && row.annotations[j].colour != java.awt.Color.black)
364    {
365  8796 text.append(comma + "[" + jalview.util.Format
366    .getHexString(row.annotations[j].colour) + "]");
367  8796 comma = ",";
368    }
369    }
370  11098 text.append("|");
371    }
372   
373  80 if (row.hasScore())
374    {
375  0 text.append("\t" + row.score);
376    }
377   
378  80 text.append(newline);
379   
380  80 if (color != null && color != java.awt.Color.black && oneColour)
381    {
382  68 colours.append("COLOUR\t");
383  68 colours.append(row.label);
384  68 colours.append("\t");
385  68 colours.append(jalview.util.Format.getHexString(color));
386  68 colours.append(newline);
387    }
388  80 if (row.scaleColLabel || row.showAllColLabels
389    || row.centreColLabels)
390    {
391  0 rowprops.append("ROWPROPERTIES\t");
392  0 rowprops.append(row.label);
393  0 rowprops.append("\tscaletofit=");
394  0 rowprops.append(row.scaleColLabel);
395  0 rowprops.append("\tshowalllabs=");
396  0 rowprops.append(row.showAllColLabels);
397  0 rowprops.append("\tcentrelabs=");
398  0 rowprops.append(row.centreColLabels);
399  0 rowprops.append(newline);
400    }
401  80 if (graphLine.length() > 0)
402    {
403  62 text.append(graphLine.toString());
404  62 graphLine.setLength(0);
405    }
406    }
407   
408  4 text.append(newline);
409   
410  4 text.append(colours.toString());
411  4 if (graphGroup.size() > 0)
412    {
413  4 SequenceI oldRefSeq = refSeq;
414  4 SequenceGroup oldRefGroup = refGroup;
415  4 for (Map.Entry<Integer, String> combine_statement : graphGroup
416    .entrySet())
417    {
418  33 Object[] seqRefAndGroup = graphGroup_refs
419    .get(combine_statement.getKey());
420   
421  33 writeSequence_Ref(refSeq, (SequenceI) seqRefAndGroup[0]);
422  33 refSeq = (SequenceI) seqRefAndGroup[0];
423   
424  33 writeGroup_Ref(refGroup, (SequenceGroup) seqRefAndGroup[1]);
425  33 refGroup = (SequenceGroup) seqRefAndGroup[1];
426  33 text.append("COMBINE\t");
427  33 text.append(combine_statement.getValue());
428  33 text.append(newline);
429    }
430  4 writeSequence_Ref(refSeq, oldRefSeq);
431  4 refSeq = oldRefSeq;
432   
433  4 writeGroup_Ref(refGroup, oldRefGroup);
434  4 refGroup = oldRefGroup;
435    }
436  4 text.append(rowprops.toString());
437    }
438   
439  5 if (list != null)
440    {
441  5 printGroups(list);
442    }
443   
444  5 if (properties != null)
445    {
446  0 text.append(newline);
447  0 text.append(newline);
448  0 text.append("ALIGNMENT");
449  0 Enumeration en = properties.keys();
450  0 while (en.hasMoreElements())
451    {
452  0 String key = en.nextElement().toString();
453  0 text.append("\t");
454  0 text.append(key);
455  0 text.append("=");
456  0 text.append(properties.get(key));
457    }
458    // TODO: output alignment visualization settings here if required
459    // iterate through one or more views, defining, marking columns and rows
460    // as visible/hidden, and emmitting view properties.
461    // View specific annotation is
462    }
463   
464  5 return text.toString();
465    }
466   
 
467  117 toggle private Object writeGroup_Ref(SequenceGroup refGroup,
468    SequenceGroup next_refGroup)
469    {
470  117 if (next_refGroup == null)
471    {
472   
473  117 if (refGroup != null)
474    {
475  0 text.append(newline);
476  0 text.append("GROUP_REF\t");
477  0 text.append("ALIGNMENT");
478  0 text.append(newline);
479    }
480  117 return true;
481    }
482    else
483    {
484  0 if (refGroup == null || refGroup != next_refGroup)
485    {
486  0 text.append(newline);
487  0 text.append("GROUP_REF\t");
488  0 text.append(next_refGroup.getName());
489  0 text.append(newline);
490  0 return true;
491    }
492    }
493  0 return false;
494    }
495   
 
496  117 toggle private boolean writeSequence_Ref(SequenceI refSeq, SequenceI next_refSeq)
497    {
498   
499  117 if (next_refSeq == null)
500    {
501  6 if (refSeq != null)
502    {
503  0 text.append(newline);
504  0 text.append("SEQUENCE_REF\t");
505  0 text.append("ALIGNMENT");
506  0 text.append(newline);
507  0 return true;
508    }
509    }
510    else
511    {
512  111 if (refSeq == null || refSeq != next_refSeq)
513    {
514  62 text.append(newline);
515  62 text.append("SEQUENCE_REF\t");
516  62 text.append(next_refSeq.getName());
517  62 text.append(newline);
518  62 return true;
519    }
520    }
521  55 return false;
522    }
523   
 
524  5 toggle protected void printGroups(List<SequenceGroup> list)
525    {
526  5 SequenceI seqrep = null;
527  5 for (SequenceGroup sg : list)
528    {
529  6 if (!sg.hasSeqrep())
530    {
531  2 text.append("SEQUENCE_GROUP\t" + sg.getName() + "\t"
532    + (sg.getStartRes() + 1) + "\t" + (sg.getEndRes() + 1)
533    + "\t" + "-1\t");
534  2 seqrep = null;
535    }
536    else
537    {
538  4 seqrep = sg.getSeqrep();
539  4 text.append("SEQUENCE_REF\t");
540  4 text.append(seqrep.getName());
541  4 text.append(newline);
542  4 text.append("SEQUENCE_GROUP\t");
543  4 text.append(sg.getName());
544  4 text.append("\t");
545  4 text.append((seqrep.findPosition(sg.getStartRes())));
546  4 text.append("\t");
547  4 text.append((seqrep.findPosition(sg.getEndRes())));
548  4 text.append("\t");
549  4 text.append("-1\t");
550    }
551  47 for (int s = 0; s < sg.getSize(); s++)
552    {
553  41 text.append(sg.getSequenceAt(s).getName());
554  41 text.append("\t");
555    }
556  6 text.append(newline);
557  6 text.append("PROPERTIES\t");
558  6 text.append(sg.getName());
559  6 text.append("\t");
560   
561  6 if (sg.getDescription() != null)
562    {
563  2 text.append("description=");
564  2 text.append(sg.getDescription());
565  2 text.append("\t");
566    }
567  6 if (sg.cs != null)
568    {
569  6 text.append("colour=");
570  6 text.append(ColourSchemeProperty
571    .getColourName(sg.cs.getColourScheme()));
572  6 text.append("\t");
573  6 if (sg.cs.getThreshold() != 0)
574    {
575  0 text.append("pidThreshold=");
576  0 text.append(sg.cs.getThreshold());
577    }
578  6 if (sg.cs.conservationApplied())
579    {
580  0 text.append("consThreshold=");
581  0 text.append(sg.cs.getConservationInc());
582  0 text.append("\t");
583    }
584    }
585  6 text.append("outlineColour=");
586  6 text.append(jalview.util.Format.getHexString(sg.getOutlineColour()));
587  6 text.append("\t");
588   
589  6 text.append("displayBoxes=");
590  6 text.append(sg.getDisplayBoxes());
591  6 text.append("\t");
592  6 text.append("displayText=");
593  6 text.append(sg.getDisplayText());
594  6 text.append("\t");
595  6 text.append("colourText=");
596  6 text.append(sg.getColourText());
597  6 text.append("\t");
598  6 text.append("showUnconserved=");
599  6 text.append(sg.getShowNonconserved());
600  6 text.append("\t");
601  6 if (sg.textColour != java.awt.Color.black)
602    {
603  0 text.append("textCol1=");
604  0 text.append(jalview.util.Format.getHexString(sg.textColour));
605  0 text.append("\t");
606    }
607  6 if (sg.textColour2 != java.awt.Color.white)
608    {
609  2 text.append("textCol2=");
610  2 text.append(jalview.util.Format.getHexString(sg.textColour2));
611  2 text.append("\t");
612    }
613  6 if (sg.thresholdTextColour != 0)
614    {
615  0 text.append("textColThreshold=");
616  0 text.append(sg.thresholdTextColour);
617  0 text.append("\t");
618    }
619  6 if (sg.idColour != null)
620    {
621  0 text.append("idColour=");
622  0 text.append(jalview.util.Format.getHexString(sg.idColour));
623  0 text.append("\t");
624    }
625  6 if (sg.isHidereps())
626    {
627  0 text.append("hide=true\t");
628    }
629  6 if (sg.isHideCols())
630    {
631  0 text.append("hidecols=true\t");
632    }
633  6 if (seqrep != null)
634    {
635    // terminate the last line and clear the sequence ref for the group
636  4 text.append(newline);
637  4 text.append("SEQUENCE_REF");
638    }
639  6 text.append(newline);
640  6 text.append(newline);
641   
642    }
643    }
644   
645    SequenceI refSeq = null;
646   
647    String refSeqId = null;
648   
 
649  5 toggle public boolean annotateAlignmentView(AlignViewportI viewport, Object file,
650    DataSourceType protocol)
651    {
652  5 ColumnSelection colSel = viewport.getColumnSelection();
653  5 HiddenColumns hidden = viewport.getAlignment().getHiddenColumns();
654  5 if (colSel == null)
655    {
656  0 colSel = new ColumnSelection();
657    }
658  5 if (hidden == null)
659    {
660  0 hidden = new HiddenColumns();
661    }
662  5 boolean rslt = readAnnotationFile(viewport.getAlignment(), hidden, file,
663    protocol);
664  5 if (rslt && (colSel.hasSelectedColumns() || hidden.hasHiddenColumns()))
665    {
666  0 viewport.setColumnSelection(colSel);
667  0 viewport.getAlignment().setHiddenColumns(hidden);
668    }
669   
670  5 return rslt;
671    }
672   
 
673  8 toggle public boolean readAnnotationFile(AlignmentI al, String file,
674    DataSourceType sourceType)
675    {
676  8 return readAnnotationFile(al, null, file, sourceType);
677    }
678   
 
679  18 toggle public boolean readAnnotationFile(AlignmentI al, HiddenColumns hidden,
680    Object file, DataSourceType sourceType)
681    {
682  18 BufferedReader in = null;
683  18 try
684    {
685  18 if (sourceType == DataSourceType.FILE)
686    {
687  9 in = FileLoader.getBuffereReader(file);
688    }
689  9 else if (sourceType == DataSourceType.URL)
690    {
691  0 URL url = new URL(file.toString());
692  0 in = new BufferedReader(new InputStreamReader(url.openStream()));
693    }
694  9 else if (sourceType == DataSourceType.PASTE)
695    {
696  9 in = new BufferedReader(new StringReader(file.toString()));
697    }
698  0 else if (sourceType == DataSourceType.CLASSLOADER)
699    {
700  0 java.io.InputStream is = getClass().getResourceAsStream("/" + file);
701  0 if (is != null)
702    {
703  0 in = new BufferedReader(new java.io.InputStreamReader(is));
704    }
705    }
706  18 if (in != null)
707    {
708  18 return parseAnnotationFrom(al, hidden, in);
709    }
710   
711    } catch (Exception ex)
712    {
713  0 ex.printStackTrace();
714  0 System.out.println("Problem reading annotation file: " + ex);
715  0 if (nlinesread > 0)
716    {
717  0 System.out.println("Last read line " + nlinesread + ": '" + lastread
718    + "' (first 80 chars) ...");
719    }
720  0 return false;
721    }
722  0 return false;
723    }
724   
725    long nlinesread = 0;
726   
727    String lastread = "";
728   
729    private static String GRAPHLINE = "GRAPHLINE", COMBINE = "COMBINE";
730   
 
731  18 toggle public boolean parseAnnotationFrom(AlignmentI al, HiddenColumns hidden,
732    BufferedReader in) throws Exception
733    {
734  18 nlinesread = 0;
735  18 ArrayList<Object[]> combineAnnotation_calls = new ArrayList<>();
736  18 ArrayList<Object[]> deferredAnnotation_calls = new ArrayList<>();
737  18 boolean modified = false;
738  18 String groupRef = null;
739  18 Hashtable groupRefRows = new Hashtable();
740   
741  18 Hashtable autoAnnots = new Hashtable();
742    {
743  18 String line, label, description, token;
744  18 int graphStyle, index;
745  18 int refSeqIndex = 1;
746  18 int existingAnnotations = 0;
747    // when true - will add new rows regardless of whether they are duplicate
748    // auto-annotation like consensus or conservation graphs
749  18 boolean overrideAutoAnnot = false;
750  18 if (al.getAlignmentAnnotation() != null)
751    {
752  5 existingAnnotations = al.getAlignmentAnnotation().length;
753  5 if (existingAnnotations > 0)
754    {
755  5 AlignmentAnnotation[] aa = al.getAlignmentAnnotation();
756  25 for (int aai = 0; aai < aa.length; aai++)
757    {
758  20 if (aa[aai].autoCalculated)
759    {
760    // make a note of the name and description
761  20 autoAnnots.put(
762    autoAnnotsKey(aa[aai], aa[aai].sequenceRef,
763  20 (aa[aai].groupRef == null ? null
764    : aa[aai].groupRef.getName())),
765    new Integer(1));
766    }
767    }
768    }
769    }
770   
771  18 int alWidth = al.getWidth();
772   
773  18 StringTokenizer st;
774  18 Annotation[] annotations;
775  18 AlignmentAnnotation annotation = null;
776   
777    // First confirm this is an Annotation file
778  18 boolean jvAnnotationFile = false;
779  ? while ((line = in.readLine()) != null)
780    {
781  138 nlinesread++;
782  138 lastread = new String(line);
783  138 if (line.indexOf("#") == 0)
784    {
785  18 continue;
786    }
787   
788  120 if (line.indexOf("JALVIEW_ANNOTATION") > -1)
789    {
790  15 jvAnnotationFile = true;
791  15 break;
792    }
793    }
794   
795  18 if (!jvAnnotationFile)
796    {
797  3 in.close();
798  3 return false;
799    }
800   
801  ? while ((line = in.readLine()) != null)
802    {
803  1012 nlinesread++;
804  1012 lastread = new String(line);
805  1012 if (line.indexOf("#") == 0
806    || line.indexOf("JALVIEW_ANNOTATION") > -1
807    || line.length() == 0)
808    {
809  205 continue;
810    }
811   
812  807 st = new StringTokenizer(line, "\t");
813  807 token = st.nextToken();
814  807 if (token.equalsIgnoreCase("COLOUR"))
815    {
816    // TODO: use graduated colour def'n here too
817  168 colourAnnotations(al, st.nextToken(), st.nextToken());
818  168 modified = true;
819  168 continue;
820    }
821   
822  639 else if (token.equalsIgnoreCase(COMBINE))
823    {
824    // keep a record of current state and resolve groupRef at end
825  81 combineAnnotation_calls
826    .add(new Object[]
827    { st, refSeq, groupRef });
828  81 modified = true;
829  81 continue;
830    }
831  558 else if (token.equalsIgnoreCase("ROWPROPERTIES"))
832    {
833  3 addRowProperties(al, st);
834  3 modified = true;
835  3 continue;
836    }
837  555 else if (token.equalsIgnoreCase(GRAPHLINE))
838    {
839    // resolve at end
840  154 deferredAnnotation_calls
841    .add(new Object[]
842    { GRAPHLINE, st, refSeq, groupRef });
843  154 modified = true;
844  154 continue;
845    }
846   
847  401 else if (token.equalsIgnoreCase("SEQUENCE_REF"))
848    {
849  165 if (st.hasMoreTokens())
850    {
851  161 refSeq = al.findName(refSeqId = st.nextToken());
852  161 if (refSeq == null)
853    {
854  0 refSeqId = null;
855    }
856  161 try
857    {
858  161 refSeqIndex = Integer.parseInt(st.nextToken());
859  2 if (refSeqIndex < 1)
860    {
861  0 refSeqIndex = 1;
862  0 System.out.println(
863    "WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile");
864    }
865    } catch (Exception ex)
866    {
867  159 refSeqIndex = 1;
868    }
869    }
870    else
871    {
872  4 refSeq = null;
873  4 refSeqId = null;
874    }
875  165 continue;
876    }
877  236 else if (token.equalsIgnoreCase("GROUP_REF"))
878    {
879    // Group references could be forward or backwards, so they are
880    // resolved after the whole file is read in
881  0 groupRef = null;
882  0 if (st.hasMoreTokens())
883    {
884  0 groupRef = st.nextToken();
885  0 if (groupRef.length() < 1)
886    {
887  0 groupRef = null; // empty string
888    }
889    else
890    {
891  0 if (groupRefRows.get(groupRef) == null)
892    {
893  0 groupRefRows.put(groupRef, new Vector());
894    }
895    }
896    }
897  0 continue;
898    }
899  236 else if (token.equalsIgnoreCase("SEQUENCE_GROUP"))
900    {
901  19 addGroup(al, st);
902  19 modified = true;
903  19 continue;
904    }
905   
906  217 else if (token.equalsIgnoreCase("PROPERTIES"))
907    {
908  17 addProperties(al, st);
909  17 modified = true;
910  17 continue;
911    }
912   
913  200 else if (token.equalsIgnoreCase("BELOW_ALIGNMENT"))
914    {
915  0 setBelowAlignment(al, st);
916  0 modified = true;
917  0 continue;
918    }
919  200 else if (token.equalsIgnoreCase("ALIGNMENT"))
920    {
921  0 addAlignmentDetails(al, st);
922  0 modified = true;
923  0 continue;
924    }
925    // else if (token.equalsIgnoreCase("VIEW_DEF"))
926    // {
927    // addOrSetView(al,st);
928    // modified = true;
929    // continue;
930    // }
931  200 else if (token.equalsIgnoreCase("VIEW_SETREF"))
932    {
933  2 if (refSeq != null)
934    {
935  1 al.setSeqrep(refSeq);
936    }
937  2 modified = true;
938  2 continue;
939    }
940  198 else if (token.equalsIgnoreCase("VIEW_HIDECOLS"))
941    {
942  1 if (st.hasMoreTokens())
943    {
944  1 if (hidden == null)
945    {
946  1 hidden = new HiddenColumns();
947    }
948  1 parseHideCols(hidden, st.nextToken());
949    }
950  1 modified = true;
951  1 continue;
952    }
953  197 else if (token.equalsIgnoreCase("HIDE_INSERTIONS"))
954    {
955  1 SequenceI sr = refSeq == null ? al.getSeqrep() : refSeq;
956  1 if (sr == null)
957    {
958  0 sr = al.getSequenceAt(0);
959    }
960  1 if (sr != null)
961    {
962  1 if (hidden == null)
963    {
964  0 System.err.println(
965    "Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: "
966    + line);
967    }
968    else
969    {
970    // consider deferring this till after the file has been parsed ?
971  1 hidden.hideList(sr.getInsertions());
972    }
973    }
974  1 modified = true;
975  1 continue;
976    }
977   
978    // Parse out the annotation row
979  196 graphStyle = AlignmentAnnotation.getGraphValueFromString(token);
980  196 label = st.nextToken();
981   
982  196 index = 0;
983  196 annotations = new Annotation[alWidth];
984  196 description = null;
985  196 float score = Float.NaN;
986   
987  196 if (st.hasMoreTokens())
988    {
989  196 line = st.nextToken();
990   
991  196 if (line.indexOf("|") == -1)
992    {
993  172 description = line;
994  172 if (st.hasMoreTokens())
995    {
996  172 line = st.nextToken();
997    }
998    }
999   
1000  196 if (st.hasMoreTokens())
1001    {
1002    // This must be the score
1003  3 score = Float.valueOf(st.nextToken()).floatValue();
1004    }
1005   
1006  196 st = new StringTokenizer(line, "|", true);
1007   
1008  196 boolean emptyColumn = true;
1009  196 boolean onlyOneElement = (st.countTokens() == 1);
1010   
1011  47921 while (st.hasMoreElements() && index < alWidth)
1012    {
1013  47725 token = st.nextToken().trim();
1014   
1015  47725 if (onlyOneElement)
1016    {
1017  0 try
1018    {
1019  0 score = Float.valueOf(token).floatValue();
1020  0 break;
1021    } catch (NumberFormatException ex)
1022    {
1023    }
1024    }
1025   
1026  47725 if (token.equals("|"))
1027    {
1028  24832 if (emptyColumn)
1029    {
1030  1966 index++;
1031    }
1032   
1033  24832 emptyColumn = true;
1034    }
1035    else
1036    {
1037  22893 annotations[index++] = parseAnnotation(token, graphStyle);
1038  22893 emptyColumn = false;
1039    }
1040    }
1041   
1042    }
1043   
1044  196 annotation = new AlignmentAnnotation(label, description,
1045  196 (index == 0) ? null : annotations, 0, 0, graphStyle);
1046   
1047  196 annotation.score = score;
1048  196 if (!overrideAutoAnnot && autoAnnots
1049    .containsKey(autoAnnotsKey(annotation, refSeq, groupRef)))
1050    {
1051    // skip - we've already got an automatic annotation of this type.
1052  3 continue;
1053    }
1054    // otherwise add it!
1055  193 if (refSeq != null)
1056    {
1057   
1058  181 annotation.belowAlignment = false;
1059    // make a copy of refSeq so we can find other matches in the alignment
1060  181 SequenceI referedSeq = refSeq;
1061  181 do
1062    {
1063    // copy before we do any mapping business.
1064    // TODO: verify that undo/redo with 1:many sequence associated
1065    // annotations can be undone correctly
1066  181 AlignmentAnnotation ann = new AlignmentAnnotation(annotation);
1067  181 annotation.createSequenceMapping(referedSeq, refSeqIndex,
1068    false);
1069  181 annotation.adjustForAlignment();
1070  181 referedSeq.addAlignmentAnnotation(annotation);
1071  181 al.addAnnotation(annotation);
1072  181 al.setAnnotationIndex(annotation,
1073    al.getAlignmentAnnotation().length - existingAnnotations
1074    - 1);
1075  181 if (groupRef != null)
1076    {
1077  0 ((Vector) groupRefRows.get(groupRef)).addElement(annotation);
1078    }
1079    // and recover our virgin copy to use again if necessary.
1080  181 annotation = ann;
1081   
1082  ? } while (refSeqId != null && (referedSeq = al.findName(referedSeq,
1083    refSeqId, true)) != null);
1084    }
1085    else
1086    {
1087  12 al.addAnnotation(annotation);
1088  12 al.setAnnotationIndex(annotation,
1089    al.getAlignmentAnnotation().length - existingAnnotations
1090    - 1);
1091  12 if (groupRef != null)
1092    {
1093  0 ((Vector) groupRefRows.get(groupRef)).addElement(annotation);
1094    }
1095    }
1096    // and set modification flag
1097  193 modified = true;
1098    }
1099    // Resolve the groupRefs
1100  15 Hashtable<String, SequenceGroup> groupRefLookup = new Hashtable<>();
1101  15 Enumeration en = groupRefRows.keys();
1102   
1103  15 while (en.hasMoreElements())
1104    {
1105  0 groupRef = (String) en.nextElement();
1106  0 boolean matched = false;
1107    // Resolve group: TODO: add a getGroupByName method to alignments
1108  0 for (SequenceGroup theGroup : al.getGroups())
1109    {
1110  0 if (theGroup.getName().equals(groupRef))
1111    {
1112  0 if (matched)
1113    {
1114    // TODO: specify and implement duplication of alignment annotation
1115    // for multiple group references.
1116  0 System.err.println(
1117    "Ignoring 1:many group reference mappings for group name '"
1118    + groupRef + "'");
1119    }
1120    else
1121    {
1122  0 matched = true;
1123  0 Vector rowset = (Vector) groupRefRows.get(groupRef);
1124  0 groupRefLookup.put(groupRef, theGroup);
1125  0 if (rowset != null && rowset.size() > 0)
1126    {
1127  0 AlignmentAnnotation alan = null;
1128  0 for (int elm = 0, elmSize = rowset
1129  0 .size(); elm < elmSize; elm++)
1130    {
1131  0 alan = (AlignmentAnnotation) rowset.elementAt(elm);
1132  0 alan.groupRef = theGroup;
1133    }
1134    }
1135    }
1136    }
1137    }
1138  0 ((Vector) groupRefRows.get(groupRef)).removeAllElements();
1139    }
1140    // process any deferred attribute settings for each context
1141  15 for (Object[] _deferred_args : deferredAnnotation_calls)
1142    {
1143  154 if (_deferred_args[0] == GRAPHLINE)
1144    {
1145  154 addLine(al, (StringTokenizer) _deferred_args[1], // st
1146    (SequenceI) _deferred_args[2], // refSeq
1147  154 (_deferred_args[3] == null) ? null
1148    : groupRefLookup.get(_deferred_args[3]) // the
1149    // reference
1150    // group, or
1151    // null
1152    );
1153    }
1154    }
1155   
1156    // finally, combine all the annotation rows within each context.
1157    /**
1158    * number of combine statements in this annotation file. Used to create
1159    * new groups for combined annotation graphs without disturbing existing
1160    * ones
1161    */
1162  15 int combinecount = 0;
1163  15 for (Object[] _combine_args : combineAnnotation_calls)
1164    {
1165  81 combineAnnotations(al, ++combinecount,
1166    (StringTokenizer) _combine_args[0], // st
1167    (SequenceI) _combine_args[1], // refSeq
1168  81 (_combine_args[2] == null) ? null
1169    : groupRefLookup.get(_combine_args[2]) // the reference
1170    // group,
1171    // or null
1172    );
1173    }
1174    }
1175  15 return modified;
1176    }
1177   
 
1178  1 toggle private void parseHideCols(HiddenColumns hidden, String nextToken)
1179    {
1180  1 StringTokenizer inval = new StringTokenizer(nextToken, ",");
1181  7 while (inval.hasMoreTokens())
1182    {
1183  6 String range = inval.nextToken().trim();
1184  6 int from, to = range.indexOf("-");
1185  6 if (to == -1)
1186    {
1187  0 from = to = Integer.parseInt(range);
1188  0 if (from >= 0)
1189    {
1190  0 hidden.hideColumns(from, to);
1191    }
1192    }
1193    else
1194    {
1195  6 from = Integer.parseInt(range.substring(0, to));
1196  6 if (to < range.length() - 1)
1197    {
1198  6 to = Integer.parseInt(range.substring(to + 1));
1199    }
1200    else
1201    {
1202  0 to = from;
1203    }
1204  6 if (from > 0 && to >= from)
1205    {
1206  6 hidden.hideColumns(from, to);
1207    }
1208    }
1209    }
1210    }
1211   
 
1212  216 toggle private Object autoAnnotsKey(AlignmentAnnotation annotation,
1213    SequenceI refSeq, String groupRef)
1214    {
1215  216 return annotation.graph + "\t" + annotation.label + "\t"
1216    + annotation.description + "\t"
1217  216 + (refSeq != null ? refSeq.getDisplayId(true) : "");
1218    }
1219   
 
1220  22893 toggle Annotation parseAnnotation(String string, int graphStyle)
1221    {
1222    // don't do the glyph test if we don't want secondary structure
1223  22893 boolean hasSymbols = (graphStyle == AlignmentAnnotation.NO_GRAPH);
1224  22893 String desc = null, displayChar = null;
1225  22893 char ss = ' '; // secondaryStructure
1226  22893 float value = 0;
1227  22893 boolean parsedValue = false, dcset = false;
1228   
1229    // find colour here
1230  22893 Color colour = null;
1231  22893 int i = string.indexOf("[");
1232  22893 int j = string.indexOf("]");
1233  22893 if (i > -1 && j > -1)
1234    {
1235  21882 colour = ColorUtils.parseColourString(string.substring(i + 1, j));
1236  21882 if (i > 0 && string.charAt(i - 1) == ',')
1237    {
1238    // clip the preceding comma as well
1239  21882 i--;
1240    }
1241  21882 string = string.substring(0, i) + string.substring(j + 1);
1242    }
1243   
1244  22893 StringTokenizer st = new StringTokenizer(string, ",", true);
1245  22893 String token;
1246  22893 boolean seenContent = false;
1247  22893 int pass = 0;
1248  93560 while (st.hasMoreTokens())
1249    {
1250  70667 pass++;
1251  70667 token = st.nextToken().trim();
1252  70667 if (token.equals(","))
1253    {
1254  23889 if (!seenContent && parsedValue && !dcset)
1255    {
1256    // allow the value below the bar/line to be empty
1257  0 dcset = true;
1258  0 displayChar = " ";
1259    }
1260  23889 seenContent = false;
1261  23889 continue;
1262    }
1263    else
1264    {
1265  46778 seenContent = true;
1266    }
1267   
1268  46778 if (!parsedValue)
1269    {
1270  22903 try
1271    {
1272  22903 displayChar = token;
1273    // foo
1274  22903 value = new Float(token).floatValue();
1275  22783 parsedValue = true;
1276  22783 continue;
1277    } catch (NumberFormatException ex)
1278    {
1279    }
1280    }
1281    else
1282    {
1283  23875 if (token.length() == 1)
1284    {
1285  1308 displayChar = token;
1286    }
1287    }
1288  23995 if (hasSymbols && (token.length() == 1
1289    && "()<>[]{}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
1290    .contains(token)))
1291    {
1292    // Either this character represents a helix or sheet
1293    // or an integer which can be displayed
1294  104 ss = token.charAt(0);
1295  104 if (displayChar.equals(token.substring(0, 1)))
1296    {
1297  104 displayChar = "";
1298    }
1299    }
1300  23891 else if (desc == null || (parsedValue && pass > 2))
1301    {
1302  23889 desc = token;
1303    }
1304   
1305    }
1306    // if (!dcset && string.charAt(string.length() - 1) == ',')
1307    // {
1308    // displayChar = " "; // empty display char symbol.
1309    // }
1310  22893 if (displayChar != null && desc != null && desc.length() == 1)
1311    {
1312  72 if (displayChar.length() > 1)
1313    {
1314    // switch desc and displayChar - legacy support
1315  0 String tmp = displayChar;
1316  0 displayChar = desc;
1317  0 desc = tmp;
1318    }
1319    else
1320    {
1321  72 if (displayChar.equals(desc))
1322    {
1323    // duplicate label - hangover from the 'robust parser' above
1324  72 desc = null;
1325    }
1326    }
1327    }
1328  22893 Annotation anot = new Annotation(displayChar, desc, ss, value);
1329   
1330  22893 anot.colour = colour;
1331   
1332  22893 return anot;
1333    }
1334   
 
1335  168 toggle void colourAnnotations(AlignmentI al, String label, String colour)
1336    {
1337  168 Color awtColour = ColorUtils.parseColourString(colour);
1338  168 Annotation[] annotations;
1339  5278 for (int i = 0; i < al.getAlignmentAnnotation().length; i++)
1340    {
1341  5110 if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(label))
1342    {
1343  2266 annotations = al.getAlignmentAnnotation()[i].annotations;
1344  358028 for (int j = 0; j < annotations.length; j++)
1345    {
1346  355762 if (annotations[j] != null)
1347    {
1348  303318 annotations[j].colour = awtColour;
1349    }
1350    }
1351    }
1352    }
1353    }
1354   
 
1355  81 toggle void combineAnnotations(AlignmentI al, int combineCount,
1356    StringTokenizer st, SequenceI seqRef, SequenceGroup groupRef)
1357    {
1358  81 String group = st.nextToken();
1359    // First make sure we are not overwriting the graphIndex
1360  81 int graphGroup = 0;
1361  81 if (al.getAlignmentAnnotation() != null)
1362    {
1363  1321 for (int i = 0; i < al.getAlignmentAnnotation().length; i++)
1364    {
1365  1321 AlignmentAnnotation aa = al.getAlignmentAnnotation()[i];
1366   
1367  1321 if (aa.graphGroup > graphGroup)
1368    {
1369    // try to number graphGroups in order of occurence.
1370  113 graphGroup = aa.graphGroup + 1;
1371    }
1372  1321 if (aa.sequenceRef == seqRef && aa.groupRef == groupRef
1373    && aa.label.equalsIgnoreCase(group))
1374    {
1375  81 if (aa.graphGroup > -1)
1376    {
1377  0 graphGroup = aa.graphGroup;
1378    }
1379    else
1380    {
1381  81 if (graphGroup <= combineCount)
1382    {
1383  66 graphGroup = combineCount + 1;
1384    }
1385  81 aa.graphGroup = graphGroup;
1386    }
1387  81 break;
1388    }
1389    }
1390   
1391    // Now update groups
1392  162 while (st.hasMoreTokens())
1393    {
1394  81 group = st.nextToken();
1395  1402 for (int i = 0; i < al.getAlignmentAnnotation().length; i++)
1396    {
1397  1402 AlignmentAnnotation aa = al.getAlignmentAnnotation()[i];
1398  1402 if (aa.sequenceRef == seqRef && aa.groupRef == groupRef
1399    && aa.label.equalsIgnoreCase(group))
1400    {
1401  81 aa.graphGroup = graphGroup;
1402  81 break;
1403    }
1404    }
1405    }
1406    }
1407    else
1408    {
1409  0 System.err.println(
1410    "Couldn't combine annotations. None are added to alignment yet!");
1411    }
1412    }
1413   
 
1414  154 toggle void addLine(AlignmentI al, StringTokenizer st, SequenceI seqRef,
1415    SequenceGroup groupRef)
1416    {
1417  154 String group = st.nextToken();
1418  154 AlignmentAnnotation[] alannot = al.getAlignmentAnnotation();
1419  154 String nextToken = st.nextToken();
1420  154 float value = 0f;
1421  154 try
1422    {
1423  154 value = Float.valueOf(nextToken);
1424    } catch (NumberFormatException e)
1425    {
1426  0 System.err.println("line " + nlinesread + ": Threshold '" + nextToken
1427    + "' invalid, setting to zero");
1428    }
1429  154 String label = st.hasMoreTokens() ? st.nextToken() : null;
1430  154 Color colour = null;
1431  154 if (st.hasMoreTokens())
1432    {
1433  154 colour = ColorUtils.parseColourString(st.nextToken());
1434    }
1435  154 if (alannot != null)
1436    {
1437  5162 for (int i = 0; i < alannot.length; i++)
1438    {
1439  5008 if (alannot[i].label.equalsIgnoreCase(group)
1440    && (seqRef == null || alannot[i].sequenceRef == seqRef)
1441    && (groupRef == null || alannot[i].groupRef == groupRef))
1442    {
1443  154 alannot[i].setThreshold(new GraphLine(value, label, colour));
1444    }
1445    }
1446    }
1447    }
1448   
 
1449  19 toggle void addGroup(AlignmentI al, StringTokenizer st)
1450    {
1451  19 SequenceGroup sg = new SequenceGroup();
1452  19 sg.setName(st.nextToken());
1453  19 String rng = "";
1454  19 try
1455    {
1456  19 rng = st.nextToken();
1457  19 if (rng.length() > 0 && !rng.startsWith("*"))
1458    {
1459  19 sg.setStartRes(Integer.parseInt(rng) - 1);
1460    }
1461    else
1462    {
1463  0 sg.setStartRes(0);
1464    }
1465  19 rng = st.nextToken();
1466  19 if (rng.length() > 0 && !rng.startsWith("*"))
1467    {
1468  19 sg.setEndRes(Integer.parseInt(rng) - 1);
1469    }
1470    else
1471    {
1472  0 sg.setEndRes(al.getWidth() - 1);
1473    }
1474    } catch (Exception e)
1475    {
1476  0 System.err.println(
1477    "Couldn't parse Group Start or End Field as '*' or a valid column or sequence index: '"
1478    + rng + "' - assuming alignment width for group.");
1479    // assume group is full width
1480  0 sg.setStartRes(0);
1481  0 sg.setEndRes(al.getWidth() - 1);
1482    }
1483   
1484  19 String index = st.nextToken();
1485  19 if (index.equals("-1"))
1486    {
1487  99 while (st.hasMoreElements())
1488    {
1489  84 sg.addSequence(al.findName(st.nextToken()), false);
1490    }
1491    }
1492    else
1493    {
1494  4 StringTokenizer st2 = new StringTokenizer(index, ",");
1495   
1496  8 while (st2.hasMoreTokens())
1497    {
1498  4 String tmp = st2.nextToken();
1499  4 if (tmp.equals("*"))
1500    {
1501  32 for (int i = 0; i < al.getHeight(); i++)
1502    {
1503  30 sg.addSequence(al.getSequenceAt(i), false);
1504    }
1505    }
1506  2 else if (tmp.indexOf("-") >= 0)
1507    {
1508  2 StringTokenizer st3 = new StringTokenizer(tmp, "-");
1509   
1510  2 int start = (Integer.parseInt(st3.nextToken()));
1511  2 int end = (Integer.parseInt(st3.nextToken()));
1512   
1513  2 if (end > start)
1514    {
1515  10 for (int i = start; i <= end; i++)
1516    {
1517  8 sg.addSequence(al.getSequenceAt(i - 1), false);
1518    }
1519    }
1520    }
1521    else
1522    {
1523  0 sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1),
1524    false);
1525    }
1526    }
1527    }
1528   
1529  19 if (refSeq != null)
1530    {
1531  10 sg.setStartRes(refSeq.findIndex(sg.getStartRes() + 1) - 1);
1532  10 sg.setEndRes(refSeq.findIndex(sg.getEndRes() + 1) - 1);
1533  10 sg.setSeqrep(refSeq);
1534    }
1535   
1536  19 if (sg.getSize() > 0)
1537    {
1538  17 al.addGroup(sg);
1539    }
1540    }
1541   
 
1542  3 toggle void addRowProperties(AlignmentI al, StringTokenizer st)
1543    {
1544  3 String label = st.nextToken(), keyValue, key, value;
1545  3 boolean scaletofit = false, centerlab = false, showalllabs = false;
1546  12 while (st.hasMoreTokens())
1547    {
1548  9 keyValue = st.nextToken();
1549  9 key = keyValue.substring(0, keyValue.indexOf("="));
1550  9 value = keyValue.substring(keyValue.indexOf("=") + 1);
1551  9 if (key.equalsIgnoreCase("scaletofit"))
1552    {
1553  3 scaletofit = Boolean.valueOf(value).booleanValue();
1554    }
1555  9 if (key.equalsIgnoreCase("showalllabs"))
1556    {
1557  3 showalllabs = Boolean.valueOf(value).booleanValue();
1558    }
1559  9 if (key.equalsIgnoreCase("centrelabs"))
1560    {
1561  3 centerlab = Boolean.valueOf(value).booleanValue();
1562    }
1563  9 AlignmentAnnotation[] alr = al.getAlignmentAnnotation();
1564  9 if (alr != null)
1565    {
1566  18 for (int i = 0; i < alr.length; i++)
1567    {
1568  9 if (alr[i].label.equalsIgnoreCase(label))
1569    {
1570  9 alr[i].centreColLabels = centerlab;
1571  9 alr[i].scaleColLabel = scaletofit;
1572  9 alr[i].showAllColLabels = showalllabs;
1573    }
1574    }
1575    }
1576    }
1577    }
1578   
 
1579  17 toggle void addProperties(AlignmentI al, StringTokenizer st)
1580    {
1581   
1582    // So far we have only added groups to the annotationHash,
1583    // the idea is in the future properties can be added to
1584    // alignments, other annotations etc
1585  17 if (al.getGroups() == null)
1586    {
1587  0 return;
1588    }
1589   
1590  17 String name = st.nextToken();
1591  17 SequenceGroup sg = null;
1592  17 for (SequenceGroup _sg : al.getGroups())
1593    {
1594  ? if ((sg = _sg).getName().equals(name))
1595    {
1596  15 break;
1597    }
1598    else
1599    {
1600  19 sg = null;
1601    }
1602    }
1603   
1604  17 if (sg != null)
1605    {
1606  15 String keyValue, key, value;
1607  15 ColourSchemeI def = sg.getColourScheme();
1608  113 while (st.hasMoreTokens())
1609    {
1610  98 keyValue = st.nextToken();
1611  98 key = keyValue.substring(0, keyValue.indexOf("="));
1612  98 value = keyValue.substring(keyValue.indexOf("=") + 1);
1613   
1614  98 if (key.equalsIgnoreCase("description"))
1615    {
1616  4 sg.setDescription(value);
1617    }
1618  94 else if (key.equalsIgnoreCase("colour"))
1619    {
1620  9 sg.cs.setColourScheme(
1621    ColourSchemeProperty.getColourScheme(al, value));
1622    }
1623  85 else if (key.equalsIgnoreCase("pidThreshold"))
1624    {
1625  2 sg.cs.setThreshold(Integer.parseInt(value), true);
1626   
1627    }
1628  83 else if (key.equalsIgnoreCase("consThreshold"))
1629    {
1630  0 sg.cs.setConservationInc(Integer.parseInt(value));
1631  0 Conservation c = new Conservation("Group", sg.getSequences(null),
1632    sg.getStartRes(), sg.getEndRes() + 1);
1633   
1634  0 c.calculate();
1635  0 c.verdict(false, 25); // TODO: refer to conservation percent threshold
1636   
1637  0 sg.cs.setConservation(c);
1638   
1639    }
1640  83 else if (key.equalsIgnoreCase("outlineColour"))
1641    {
1642  15 sg.setOutlineColour(ColorUtils.parseColourString(value));
1643    }
1644  68 else if (key.equalsIgnoreCase("displayBoxes"))
1645    {
1646  13 sg.setDisplayBoxes(Boolean.valueOf(value).booleanValue());
1647    }
1648  55 else if (key.equalsIgnoreCase("showUnconserved"))
1649    {
1650  11 sg.setShowNonconserved(Boolean.valueOf(value).booleanValue());
1651    }
1652  44 else if (key.equalsIgnoreCase("displayText"))
1653    {
1654  13 sg.setDisplayText(Boolean.valueOf(value).booleanValue());
1655    }
1656  31 else if (key.equalsIgnoreCase("colourText"))
1657    {
1658  13 sg.setColourText(Boolean.valueOf(value).booleanValue());
1659    }
1660  18 else if (key.equalsIgnoreCase("textCol1"))
1661    {
1662  7 sg.textColour = ColorUtils.parseColourString(value);
1663    }
1664  11 else if (key.equalsIgnoreCase("textCol2"))
1665    {
1666  9 sg.textColour2 = ColorUtils.parseColourString(value);
1667    }
1668  2 else if (key.equalsIgnoreCase("textColThreshold"))
1669    {
1670  2 sg.thresholdTextColour = Integer.parseInt(value);
1671    }
1672  0 else if (key.equalsIgnoreCase("idColour"))
1673    {
1674  0 Color idColour = ColorUtils.parseColourString(value);
1675  0 sg.setIdColour(idColour == null ? Color.black : idColour);
1676    }
1677  0 else if (key.equalsIgnoreCase("hide"))
1678    {
1679    // see bug https://mantis.lifesci.dundee.ac.uk/view.php?id=25847
1680  0 sg.setHidereps(true);
1681    }
1682  0 else if (key.equalsIgnoreCase("hidecols"))
1683    {
1684    // see bug https://mantis.lifesci.dundee.ac.uk/view.php?id=25847
1685  0 sg.setHideCols(true);
1686    }
1687  98 sg.recalcConservation();
1688    }
1689  15 if (sg.getColourScheme() == null)
1690    {
1691  11 sg.setColourScheme(def);
1692    }
1693    }
1694    }
1695   
 
1696  0 toggle void setBelowAlignment(AlignmentI al, StringTokenizer st)
1697    {
1698  0 String token;
1699  0 AlignmentAnnotation aa, ala[] = al.getAlignmentAnnotation();
1700  0 if (ala == null)
1701    {
1702  0 System.err.print(
1703    "Warning - no annotation to set below for sequence associated annotation:");
1704    }
1705  0 while (st.hasMoreTokens())
1706    {
1707  0 token = st.nextToken();
1708  0 if (ala == null)
1709    {
1710  0 System.err.print(" " + token);
1711    }
1712    else
1713    {
1714  0 for (int i = 0; i < al.getAlignmentAnnotation().length; i++)
1715    {
1716  0 aa = al.getAlignmentAnnotation()[i];
1717  0 if (aa.sequenceRef == refSeq && aa.label.equals(token))
1718    {
1719  0 aa.belowAlignment = true;
1720    }
1721    }
1722    }
1723    }
1724  0 if (ala == null)
1725    {
1726  0 System.err.print("\n");
1727    }
1728    }
1729   
 
1730  0 toggle void addAlignmentDetails(AlignmentI al, StringTokenizer st)
1731    {
1732  0 String keyValue, key, value;
1733  0 while (st.hasMoreTokens())
1734    {
1735  0 keyValue = st.nextToken();
1736  0 key = keyValue.substring(0, keyValue.indexOf("="));
1737  0 value = keyValue.substring(keyValue.indexOf("=") + 1);
1738  0 al.setProperty(key, value);
1739    }
1740    }
1741   
1742    /**
1743    * Write annotations as a CSV file of the form 'label, value, value, ...' for
1744    * each row.
1745    *
1746    * @param annotations
1747    * @return CSV file as a string.
1748    */
 
1749  0 toggle public String printCSVAnnotations(AlignmentAnnotation[] annotations)
1750    {
1751  0 if (annotations == null)
1752    {
1753  0 return "";
1754    }
1755  0 StringBuffer sp = new StringBuffer();
1756  0 for (int i = 0; i < annotations.length; i++)
1757    {
1758  0 String atos = annotations[i].toString();
1759  0 int p = 0;
1760  0 do
1761    {
1762  0 int cp = atos.indexOf("\n", p);
1763  0 sp.append(annotations[i].label);
1764  0 sp.append(",");
1765  0 if (cp > p)
1766    {
1767  0 sp.append(atos.substring(p, cp + 1));
1768    }
1769    else
1770    {
1771  0 sp.append(atos.substring(p));
1772  0 sp.append(newline);
1773    }
1774  0 p = cp + 1;
1775  0 } while (p > 0);
1776    }
1777  0 return sp.toString();
1778    }
1779   
 
1780  0 toggle public String printAnnotationsForView(AlignViewportI viewport)
1781    {
1782  0 return printAnnotations(
1783  0 viewport.isShowAnnotation()
1784    ? viewport.getAlignment().getAlignmentAnnotation()
1785    : null,
1786    viewport.getAlignment().getGroups(),
1787    viewport.getAlignment().getProperties(),
1788    viewport.getAlignment().getHiddenColumns(),
1789    viewport.getAlignment(), null);
1790    }
1791   
 
1792  0 toggle public String printAnnotationsForAlignment(AlignmentI al)
1793    {
1794  0 return printAnnotations(al.getAlignmentAnnotation(), al.getGroups(),
1795    al.getProperties(), null, al, null);
1796    }
1797    }