Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.io

File AnnotationFile.java

 

Coverage histogram

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

Code metrics

424
752
26
2
1,760
1,493
297
0.39
28.92
13
11.42

Classes

Class Line # Actions
AnnotationFile 49 748 296
0.744360974.4%
AnnotationFile.ViewDef 104 4 1
1.0100%
 

Contributing tests

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