Clover icon

Coverage Report

  1. Project Clover database Thu Jun 4 2026 15:31:54 BST
  2. Package jalview.datamodel

File AlignmentAnnotation.java

 

Coverage histogram

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

Code metrics

264
441
72
1
1,737
1,141
302
0.68
6.12
72
4.19

Classes

Class Line # Actions
AlignmentAnnotation 47 441 302
0.796653879.7%
 

Contributing tests

This file is covered by 423 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.datamodel;
22   
23    import java.awt.Color;
24    import java.util.ArrayList;
25    import java.util.Collection;
26    import java.util.Collections;
27    import java.util.HashMap;
28    import java.util.Iterator;
29    import java.util.List;
30    import java.util.Locale;
31    import java.util.Map;
32    import java.util.Map.Entry;
33   
34    import jalview.analysis.Rna;
35    import jalview.analysis.SecStrConsensus.SimpleBP;
36    import jalview.datamodel.rna.NucStructure;
37    import jalview.datamodel.rna.NucStructureI;
38    import jalview.analysis.WUSSParseException;
39    import jalview.structure.StructureImportSettings;
40   
41    /**
42    * DOCUMENT ME!
43    *
44    * @author $author$
45    * @version $Revision$
46    */
 
47    public class AlignmentAnnotation
48    {
49   
50    private static final String ANNOTATION_ID_PREFIX = "ann";
51   
52    // The property key for annotation property values like
53    // PDB id, chain code, etc
54    public static final String ANNOTATION_DETAILS = "ANNOTATION_DETAILS";
55   
56    /*
57    * Identifers for different types of profile data
58    */
59    public static final int SEQUENCE_PROFILE = 0;
60   
61    public static final int STRUCTURE_PROFILE = 1;
62   
63    public static final int CDNA_PROFILE = 2;
64   
65    private static long counter = 0;
66   
67    private long noOfSequencesIncluded = -1;
68   
69    private long noOfTracksIncluded = -1;
70   
71   
72   
73    /**
74    * If true, this annotations is calculated every edit, eg consensus, quality
75    * or conservation graphs
76    */
77    public boolean autoCalculated = false;
78   
79    /**
80    * unique ID for this annotation, used to match up the same annotation row
81    * shown in multiple views and alignments
82    */
83    public String annotationId;
84   
85    /**
86    * the sequence this annotation is associated with (or null)
87    */
88    public SequenceI sequenceRef;
89   
90    /** label shown in dropdown menus and in the annotation label area */
91    public String label;
92   
93    /** longer description text shown as a tooltip */
94    public String description;
95   
96    /** Array of annotations placed in the current coordinate system */
97    public Annotation[] annotations;
98   
99    public NucStructureI naStructure = new NucStructureI() {};
100    /**
101    * the type of temperature factor plot (if it is one)
102    */
103    private StructureImportSettings.TFType tfType = StructureImportSettings.TFType.DEFAULT;
104   
105    /**
106    * stores the colour of the group to which the annotation belongs.
107    * The label of the annotation is highlighted with this colour.
108    */
109    private Color annotationGroupColour = null;
110   
 
111  199 toggle public void setTFType(StructureImportSettings.TFType t)
112    {
113  199 tfType = t;
114    }
115   
 
116  0 toggle public StructureImportSettings.TFType getTFType()
117    {
118  0 return tfType;
119    }
120   
121    private double bitScore;
122   
123    private double eValue;
124   
125   
 
126  4922 toggle public Color getAnnotationGroupColour()
127    {
128  4922 return annotationGroupColour;
129    }
130   
 
131  442 toggle public void setAnnotationGroupColour(Color annotationGroupColour)
132    {
133  442 this.annotationGroupColour = annotationGroupColour;
134    }
135   
136    /**
137    * Get the RNA Secondary Structure SequenceFeature Array if present
138    */
 
139  1877 toggle public SequenceFeature[] getRnaSecondaryStructure()
140    {
141  1877 return naStructure.getRnaSecondaryStructure();
142    }
143   
144    /**
145    * Check the RNA Secondary Structure is equivalent to one in given
146    * AlignmentAnnotation param
147    */
 
148  4 toggle public boolean rnaSecondaryStructureEquivalent(AlignmentAnnotation that)
149    {
150  4 return naStructure.rnaSecondaryStructureEquivalent(this, that, true);
151    }
152   
153    /**
154    * map of positions in the associated annotation
155    */
156    private Map<Integer, Annotation> sequenceMapping;
157   
158    /**
159    * lower range for quantitative data
160    */
161    public float graphMin;
162   
163    /**
164    * Upper range for quantitative data
165    */
166    public float graphMax;
167   
168    /**
169    * Score associated with label and description.
170    */
171    public double score = Double.NaN;
172   
173    /**
174    * flag indicating if annotation has a score.
175    */
176    public boolean hasScore = false;
177   
178    public GraphLine threshold;
179   
180    // Graphical hints and tips
181   
182    /** Can this row be edited by the user ? */
183    public boolean editable = false;
184   
185    /** Indicates if annotation has a graphical symbol track */
186    public boolean hasIcons; //
187   
188    /** Indicates if annotation has a text character label */
189    public boolean hasText;
190   
191    /** is the row visible */
192    public boolean visible = true;
193   
194    /**
195    * is there data for this annotation row to display ? if not then hide it!
196    * For rows that are only shown when data is present (default true)
197    */
198    public boolean hasData=true;
199   
200   
201   
202    public int graphGroup = -1;
203   
204    /** Displayed height of row in pixels */
205    public int height = 0;
206   
207    public int graph = 0;
208   
209    public int graphHeight = 40;
210   
211    public boolean padGaps = false;
212   
213    public static final int NO_GRAPH = 0;
214   
215    public static final int BAR_GRAPH = 1;
216   
217    public static final int LINE_GRAPH = 2;
218   
219    public static final int CONTACT_MAP = 4;
220   
221    /**
222    * property that when set to non-empty string disables display of column
223    * groups defined on the contact matrix
224    */
225    public static final String CONTACT_MAP_NOGROUPS = "CMNOGRPS";
226   
227    public boolean belowAlignment = true;
228   
229    public SequenceGroup groupRef = null;
230   
231    /**
232    * display every column label, even if there is a row of identical labels
233    */
234    public boolean showAllColLabels = false;
235   
236    /**
237    * scale the column label to fit within the alignment column.
238    */
239    public boolean scaleColLabel = false;
240   
241    /**
242    * centre the column labels relative to the alignment column
243    */
244    public boolean centreColLabels = false;
245   
246    private boolean isrna;
247   
 
248  260 toggle public static int getGraphValueFromString(String string)
249    {
250  260 if (string.equalsIgnoreCase("BAR_GRAPH"))
251    {
252  32 return BAR_GRAPH;
253    }
254  228 else if (string.equalsIgnoreCase("LINE_GRAPH"))
255    {
256  171 return LINE_GRAPH;
257    }
258    else
259    {
260  57 return NO_GRAPH;
261    }
262    }
263   
264    /**
265    * Creates a new AlignmentAnnotation object.
266    *
267    * @param label
268    * short label shown under sequence labels
269    * @param description
270    * text displayed on mouseover
271    * @param annotations
272    * set of positional annotation elements
273    */
 
274  37064 toggle public AlignmentAnnotation(String label, String description,
275    Annotation[] annotations)
276    {
277  37064 setAnnotationId();
278    // always editable?
279  37064 editable = true;
280  37064 this.label = label;
281  37064 this.description = description;
282  37064 this.annotations = annotations;
283   
284  37064 validateRangeAndDisplay();
285    }
286   
287    /**
288    * Checks if annotation labels represent secondary structures
289    *
290    */
 
291  9011 toggle void areLabelsSecondaryStructure()
292    {
293  9011 boolean nonSSLabel = false;
294  9011 isrna = false;
295  9011 StringBuffer rnastring = new StringBuffer();
296   
297  9011 char firstChar = 0;
298  1040675 for (int i = 0; i < annotations.length; i++)
299    {
300    // DEBUG jalview.bin.Console.outPrintln(i + ": " + annotations[i]);
301  1031664 if (annotations[i] == null)
302    {
303  323577 continue;
304    }
305  708087 if (annotations[i].secondaryStructure == 'H'
306    || annotations[i].secondaryStructure == 'E')
307    {
308    // DEBUG jalview.bin.Console.outPrintln( "/H|E/ '" +
309    // annotations[i].secondaryStructure + "'");
310  58683 hasIcons |= true;
311    }
312    else
313    // Check for RNA secondary structure
314    {
315    // DEBUG jalview.bin.Console.outPrintln( "/else/ '" +
316    // annotations[i].secondaryStructure + "'");
317    // TODO: 2.8.2 should this ss symbol validation check be a function in
318    // RNA/ResidueProperties ?
319    // allow for DSSP extended code:
320    // https://www.wikidoc.org/index.php/Secondary_structure#The_DSSP_code
321    // GHITEBS as well as C and X (for missing?)
322  649404 if (annotations[i].secondaryStructure == '('
323    || annotations[i].secondaryStructure == '['
324    || annotations[i].secondaryStructure == '<'
325    || annotations[i].secondaryStructure == '{'
326    || annotations[i].secondaryStructure == 'A'
327    // || annotations[i].secondaryStructure == 'B'
328    // || annotations[i].secondaryStructure == 'C'
329    || annotations[i].secondaryStructure == 'D'
330    // || annotations[i].secondaryStructure == 'E' // ambiguous on
331    // its own -- already checked above
332    || annotations[i].secondaryStructure == 'F'
333    // || annotations[i].secondaryStructure == 'G'
334    // || annotations[i].secondaryStructure == 'H' // ambiguous on
335    // its own -- already checked above
336    // || annotations[i].secondaryStructure == 'I'
337    || annotations[i].secondaryStructure == 'J'
338    || annotations[i].secondaryStructure == 'K'
339    || annotations[i].secondaryStructure == 'L'
340    || annotations[i].secondaryStructure == 'M'
341    || annotations[i].secondaryStructure == 'N'
342    || annotations[i].secondaryStructure == 'O'
343    || annotations[i].secondaryStructure == 'P'
344    || annotations[i].secondaryStructure == 'Q'
345    || annotations[i].secondaryStructure == 'R'
346    // || annotations[i].secondaryStructure == 'S'
347    // || annotations[i].secondaryStructure == 'T'
348    || annotations[i].secondaryStructure == 'U'
349    || annotations[i].secondaryStructure == 'V'
350    || annotations[i].secondaryStructure == 'W'
351    // || annotations[i].secondaryStructure == 'X'
352    || annotations[i].secondaryStructure == 'Y'
353    || annotations[i].secondaryStructure == 'Z')
354    {
355  14987 hasIcons |= true;
356  14987 isrna |= true;
357    }
358    }
359   
360    // jalview.bin.Console.outPrintln("displaychar " +
361    // annotations[i].displayCharacter);
362   
363  708087 if (annotations[i].displayCharacter == null
364    || annotations[i].displayCharacter.length() == 0)
365    {
366  319747 rnastring.append('.');
367  319747 continue;
368    }
369  388340 if (annotations[i].displayCharacter.length() == 1)
370    {
371  328512 firstChar = annotations[i].displayCharacter.charAt(0);
372    // check to see if it looks like a sequence or is secondary structure
373    // labelling.
374  328512 if (annotations[i].secondaryStructure != ' ' && !hasIcons &&
375    // Uncomment to only catch case where
376    // displayCharacter==secondary
377    // Structure
378    // to correctly redisplay SS annotation imported from Stockholm,
379    // exported to JalviewXML and read back in again.
380    // &&
381    // annotations[i].displayCharacter.charAt(0)==annotations[i].secondaryStructure
382    firstChar != ' ' && firstChar != '$' && firstChar != 0xCE
383    && firstChar != '(' && firstChar != '[' && firstChar != '<'
384    && firstChar != '{' && firstChar != 'A' && firstChar != 'B'
385    && firstChar != 'C' && firstChar != 'D' && firstChar != 'E'
386    && firstChar != 'F' && firstChar != 'G' && firstChar != 'H'
387    && firstChar != 'I' && firstChar != 'J' && firstChar != 'K'
388    && firstChar != 'L' && firstChar != 'M' && firstChar != 'N'
389    && firstChar != 'O' && firstChar != 'P' && firstChar != 'Q'
390    && firstChar != 'R' && firstChar != 'S' && firstChar != 'T'
391    && firstChar != 'U' && firstChar != 'V' && firstChar != 'W'
392    && firstChar != 'X' && firstChar != 'Y' && firstChar != 'Z'
393    && firstChar != '-'
394    && firstChar < jalview.schemes.ResidueProperties.aaIndex.length)
395    {
396  6840 if (jalview.schemes.ResidueProperties.aaIndex[firstChar] < 23) // TODO:
397    // parameterise
398    // to
399    // gap
400    // symbol
401    // number
402    {
403  11 nonSSLabel = true;
404    }
405    }
406    }
407    else
408    {
409  59828 rnastring.append(annotations[i].displayCharacter.charAt(1));
410    }
411   
412  388340 if (annotations[i].displayCharacter.length() > 0)
413    {
414  388340 hasText = true;
415    }
416    }
417   
418  9011 if (nonSSLabel)
419    {
420  1 hasIcons = false;
421  12 for (int j = 0; j < annotations.length; j++)
422    {
423  11 if (annotations[j] != null
424    && annotations[j].secondaryStructure != ' ')
425    {
426  11 annotations[j].displayCharacter = String
427    .valueOf(annotations[j].secondaryStructure);
428  11 annotations[j].secondaryStructure = ' ';
429    }
430   
431    }
432    }
433    else
434    {
435  9010 if (isrna)
436    {
437  1045 naStructure = new NucStructure();
438  1045 naStructure.update(this);
439    }
440    }
441    }
442   
443    /**
444    * Creates a new AlignmentAnnotation object.
445    *
446    * @param label
447    * DOCUMENT ME!
448    * @param description
449    * DOCUMENT ME!
450    * @param annotations
451    * DOCUMENT ME!
452    * @param min
453    * DOCUMENT ME!
454    * @param max
455    * DOCUMENT ME!
456    * @param winLength
457    * DOCUMENT ME!
458    */
 
459  4154 toggle public AlignmentAnnotation(String label, String description,
460    Annotation[] annotations, float min, float max, int graphType)
461    {
462  4154 setAnnotationId();
463    // graphs are not editable
464  4154 editable = graphType == 0;
465   
466  4154 this.label = label;
467  4154 this.description = description;
468  4154 this.annotations = annotations;
469  4154 graph = graphType;
470  4154 graphMin = min;
471  4154 graphMax = max;
472  4154 validateRangeAndDisplay();
473    }
474   
475    /**
476    * checks graphMin and graphMax, secondary structure symbols, sets graphType
477    * appropriately, sets null labels to the empty string if appropriate.
478    */
 
479  43681 toggle public void validateRangeAndDisplay()
480    {
481   
482  43681 if (annotations == null)
483    {
484  34670 visible = false; // try to prevent renderer from displaying.
485  34670 return; // this is a non-annotation row annotation - ie a sequence score.
486    }
487   
488  9011 int graphType = graph;
489  9011 float min = graphMin;
490  9011 float max = graphMax;
491  9011 boolean drawValues = true;
492  9011 _linecolour = null;
493  9011 if (min == max)
494    {
495  4662 min = 999999999;
496  707039 for (int i = 0; i < annotations.length; i++)
497    {
498  702393 if (annotations[i] == null)
499    {
500  146297 continue;
501    }
502   
503  556096 if (drawValues && annotations[i].displayCharacter != null
504    && annotations[i].displayCharacter.length() > 1)
505    {
506  1380 drawValues = false;
507    }
508   
509  556095 if (annotations[i].value > max)
510    {
511  7002 max = annotations[i].value;
512    }
513   
514  556094 if (annotations[i].value < min)
515    {
516  8781 min = annotations[i].value;
517    }
518  556094 if (_linecolour == null && annotations[i].colour != null)
519    {
520  1676 _linecolour = annotations[i].colour;
521    }
522    }
523    // ensure zero is origin for min/max ranges on only one side of zero
524  4662 if (min > 0)
525    {
526  2256 min = 0;
527    }
528    else
529    {
530  2406 if (max < 0)
531    {
532  0 max = 0;
533    }
534    }
535    }
536   
537  9011 graphMin = min;
538  9011 graphMax = max;
539   
540  9011 areLabelsSecondaryStructure();
541   
542  9011 if (!drawValues && graphType != NO_GRAPH)
543    {
544  28597 for (int i = 0; i < annotations.length; i++)
545    {
546  28416 if (annotations[i] != null)
547    {
548  22147 annotations[i].displayCharacter = "";
549    }
550    }
551    }
552    }
553   
554    /**
555    * Copy constructor creates a new independent annotation row with the same
556    * associated sequenceRef
557    *
558    * @param annotation
559    */
 
560  1156 toggle public AlignmentAnnotation(AlignmentAnnotation annotation)
561    {
562  1156 setAnnotationId();
563  1156 updateAlignmentAnnotationFrom(annotation);
564    }
565   
566    /**
567    * copy attributes and annotation from an existing annotation (used by copy
568    * constructor). This method does not update the unique annotationId
569    *
570    * @param annotation
571    */
 
572  1158 toggle public void updateAlignmentAnnotationFrom(AlignmentAnnotation annotation)
573    {
574  1158 this.label = new String(annotation.label);
575  1158 if (annotation.description != null)
576    {
577  1068 this.description = new String(annotation.description);
578    }
579  1158 this.graphMin = annotation.graphMin;
580  1158 this.graphMax = annotation.graphMax;
581  1158 this.graph = annotation.graph;
582  1158 this.graphHeight = annotation.graphHeight;
583  1158 this.graphGroup = annotation.graphGroup;
584  1158 this.groupRef = annotation.groupRef;
585  1158 this.editable = annotation.editable;
586  1158 this.autoCalculated = annotation.autoCalculated;
587  1158 this.hasIcons = annotation.hasIcons;
588  1158 this.hasText = annotation.hasText;
589  1158 this.height = annotation.height;
590  1158 this.label = annotation.label;
591  1158 this.padGaps = annotation.padGaps;
592  1158 this.visible = annotation.visible;
593  1158 this.hasData = annotation.hasData;
594  1158 this.centreColLabels = annotation.centreColLabels;
595  1158 this.scaleColLabel = annotation.scaleColLabel;
596  1158 this.showAllColLabels = annotation.showAllColLabels;
597  1158 this.calcId = annotation.calcId;
598  1158 this.bitScore = annotation.bitScore;
599  1158 this.eValue = annotation.eValue;
600   
601  1158 if (annotation.properties != null)
602    {
603  1158 properties = new HashMap<>();
604  1158 for (Map.Entry<String, String> val : annotation.properties.entrySet())
605    {
606  708 properties.put(val.getKey(), val.getValue());
607    }
608    }
609  ? if (this.hasScore = annotation.hasScore)
610    {
611  156 this.score = annotation.score;
612    }
613  1158 if (annotation.threshold != null)
614    {
615  0 threshold = new GraphLine(annotation.threshold);
616    }
617  1158 Annotation[] ann = annotation.annotations;
618  1158 if (annotation.annotations != null)
619    {
620  1155 this.annotations = new Annotation[ann.length];
621  132043 for (int i = 0; i < ann.length; i++)
622    {
623  130888 if (ann[i] != null)
624    {
625  91451 annotations[i] = new Annotation(ann[i]);
626  91451 if (_linecolour != null)
627    {
628  0 _linecolour = annotations[i].colour;
629    }
630    }
631    }
632    }
633  1158 if (annotation.sequenceRef != null)
634    {
635  943 this.sequenceRef = annotation.sequenceRef;
636  943 if (annotation.sequenceMapping != null)
637    {
638  941 Integer p = null;
639  941 sequenceMapping = new HashMap<>();
640  941 Iterator<Integer> pos = annotation.sequenceMapping.keySet()
641    .iterator();
642  71352 while (pos.hasNext())
643    {
644    // could optimise this!
645  70411 p = pos.next();
646  70411 Annotation a = annotation.sequenceMapping.get(p);
647  70411 if (a == null)
648    {
649  0 continue;
650    }
651  70411 if (ann != null)
652    {
653  10601013 for (int i = 0; i < ann.length; i++)
654    {
655  10530602 if (ann[i] == a)
656    {
657  70393 sequenceMapping.put(p, annotations[i]);
658    }
659    }
660    }
661    }
662    }
663    else
664    {
665  2 this.sequenceMapping = null;
666    }
667   
668    }
669    // TODO: check if we need to do this: JAL-952
670    // if (this.isrna=annotation.isrna)
671    {
672    // _rnasecstr=new SequenceFeature[annotation._rnasecstr];
673    }
674  1158 validateRangeAndDisplay(); // construct hashcodes, etc.
675    }
676   
677    /**
678    * clip the annotation to the columns given by startRes and endRes (inclusive)
679    * and prune any existing sequenceMapping to just those columns.
680    *
681    * @param startRes
682    * @param endRes
683    */
 
684  131 toggle public void restrict(int startRes, int endRes)
685    {
686  131 if (annotations == null)
687    {
688    // non-positional
689  0 return;
690    }
691  131 if (startRes < 0)
692    {
693  2 startRes = 0;
694    }
695  131 if (startRes >= annotations.length)
696    {
697  5 startRes = annotations.length;
698    }
699  131 if (endRes < 0)
700    {
701  1 endRes = -1;
702    }
703  131 if (endRes >= annotations.length)
704    {
705  113 endRes = annotations.length - 1;
706    }
707  131 Annotation[] temp = new Annotation[endRes - startRes + 1];
708  131 if (startRes < annotations.length)
709    {
710  126 System.arraycopy(annotations, startRes, temp, 0,
711    endRes - startRes + 1);
712    }
713  131 if (sequenceRef != null)
714    {
715    // Clip the mapping, if it exists.
716  119 int spos = sequenceRef.findPosition(startRes);
717  119 int epos = sequenceRef.findPosition(endRes);
718  119 if (sequenceMapping != null)
719    {
720  119 Map<Integer, Annotation> newmapping = new HashMap<>();
721  119 Iterator<Integer> e = sequenceMapping.keySet().iterator();
722  8485 while (e.hasNext())
723    {
724  8366 Integer pos = e.next();
725  8366 if (pos.intValue() >= spos && pos.intValue() <= epos)
726    {
727  8322 newmapping.put(pos, sequenceMapping.get(pos));
728    }
729    }
730  119 sequenceMapping.clear();
731  119 sequenceMapping = newmapping;
732    }
733    }
734  131 annotations = temp;
735    }
736   
737    /**
738    * set the annotation row to be at least length Annotations
739    *
740    * @param length
741    * minimum number of columns required in the annotation row
742    * @return false if the annotation row is greater than length
743    */
 
744  0 toggle public boolean padAnnotation(int length)
745    {
746  0 if (annotations == null)
747    {
748  0 return true; // annotation row is correct - null == not visible and
749    // undefined length
750    }
751  0 if (annotations.length < length)
752    {
753  0 Annotation[] na = new Annotation[length];
754  0 System.arraycopy(annotations, 0, na, 0, annotations.length);
755  0 annotations = na;
756  0 return true;
757    }
758  0 return annotations.length > length;
759   
760    }
761   
762    /**
763    * DOCUMENT ME!
764    *
765    * @return DOCUMENT ME!
766    */
 
767  377 toggle @Override
768    public String toString()
769    {
770  377 if (annotations == null)
771    {
772  207 return "";
773    }
774  170 StringBuilder buffer = new StringBuilder(256);
775   
776  383 for (int i = 0; i < annotations.length; i++)
777    {
778  213 if (annotations[i] != null)
779    {
780  157 if (graph != 0)
781    {
782  25 buffer.append(annotations[i].value);
783    }
784  132 else if (hasIcons)
785    {
786  84 buffer.append(annotations[i].secondaryStructure);
787    }
788    else
789    {
790  48 buffer.append(annotations[i].displayCharacter);
791    }
792    }
793   
794  213 buffer.append(", ");
795    }
796    // TODO: remove disgusting hack for 'special' treatment of consensus line.
797  170 if (label.indexOf("Consensus") == 0)
798    {
799  10 buffer.append("\n");
800   
801  15 for (int i = 0; i < annotations.length; i++)
802    {
803  5 if (annotations[i] != null)
804    {
805  5 buffer.append(annotations[i].description);
806    }
807   
808  5 buffer.append(", ");
809    }
810    }
811   
812  170 return buffer.toString();
813    }
814   
 
815  2 toggle public void setThreshold(GraphLine line)
816    {
817  2 threshold = line;
818    }
819   
 
820  686 toggle public GraphLine getThreshold()
821    {
822  686 return threshold;
823    }
824   
825    /**
826    * Attach the annotation to seqRef, starting from startRes position. If
827    * alreadyMapped is true then the indices of the annotation[] array are
828    * sequence positions rather than alignment column positions.
829    *
830    * @param seqRef
831    * @param startRes
832    * @param alreadyMapped
833    * - annotation are at aligned columns
834    */
 
835  4383 toggle public void createSequenceMapping(SequenceI seqRef, int startRes,
836    boolean alreadyMapped)
837    {
838   
839  4383 if (seqRef == null)
840    {
841  0 return;
842    }
843  4383 sequenceRef = seqRef;
844  4383 if (annotations == null)
845    {
846  1270 return;
847    }
848  3113 sequenceMapping = new HashMap<>();
849   
850  3113 int seqPos;
851   
852  447162 for (int i = 0; i < annotations.length; i++)
853    {
854  444049 if (annotations[i] != null)
855    {
856  367368 if (alreadyMapped)
857    {
858  235256 seqPos = seqRef.findPosition(i);
859    }
860    else
861    {
862  132112 seqPos = i + startRes;
863    }
864   
865  367368 sequenceMapping.put(Integer.valueOf(seqPos), annotations[i]);
866    }
867    }
868   
869    }
870   
871    /**
872    * When positional annotation and a sequence reference is present, clears and
873    * resizes the annotations array to the current alignment width, and adds
874    * annotation according to aligned positions of the sequenceRef given by
875    * sequenceMapping.
876    */
 
877  4246 toggle public void adjustForAlignment()
878    {
879  4246 if (sequenceRef == null)
880    {
881  188 return;
882    }
883   
884  4058 if (annotations == null)
885    {
886  1270 return;
887    }
888   
889  2788 int a = 0, aSize = sequenceRef.getLength();
890   
891  2788 if (aSize == 0)
892    {
893    // Its been deleted
894  1 return;
895    }
896   
897  2787 int position;
898  2787 Annotation[] temp = new Annotation[aSize];
899  2787 Integer index;
900  2787 if (sequenceMapping != null)
901    {
902  322355 for (a = sequenceRef.getStart(); a <= sequenceRef.getEnd(); a++)
903    {
904  319568 index = Integer.valueOf(a);
905  319568 Annotation annot = sequenceMapping.get(index);
906  319568 if (annot != null)
907    {
908  254863 position = sequenceRef.findIndex(a) - 1;
909   
910  254863 temp[position] = annot;
911    }
912    }
913    }
914  2787 annotations = temp;
915    }
916   
917    /**
918    * remove any null entries in annotation row and return the number of non-null
919    * annotation elements.
920    *
921    * @return
922    */
 
923  0 toggle public int compactAnnotationArray()
924    {
925  0 int i = 0, iSize = annotations.length;
926  0 while (i < iSize)
927    {
928  0 if (annotations[i] == null)
929    {
930  0 if (i + 1 < iSize)
931    {
932  0 System.arraycopy(annotations, i + 1, annotations, i,
933    iSize - i - 1);
934    }
935  0 iSize--;
936    }
937    else
938    {
939  0 i++;
940    }
941    }
942  0 Annotation[] ann = annotations;
943  0 annotations = new Annotation[i];
944  0 System.arraycopy(ann, 0, annotations, 0, i);
945  0 ann = null;
946  0 return iSize;
947    }
948   
949    /**
950    * Associate this annotation with the aligned residues of a particular
951    * sequence. sequenceMapping will be updated in the following way: null
952    * sequenceI - existing mapping will be discarded but annotations left in
953    * mapped positions. valid sequenceI not equal to current sequenceRef: mapping
954    * is discarded and rebuilt assuming 1:1 correspondence TODO: overload with
955    * parameter to specify correspondence between current and new sequenceRef
956    *
957    * @param sequenceI
958    */
 
959  5749 toggle public void setSequenceRef(SequenceI sequenceI)
960    {
961  5749 if (sequenceI != null)
962    {
963  5686 if (sequenceRef != null)
964    {
965  3357 boolean rIsDs = sequenceRef.getDatasetSequence() == null,
966    tIsDs = sequenceI.getDatasetSequence() == null;
967  3357 if (sequenceRef != sequenceI
968    && (rIsDs && !tIsDs
969    && sequenceRef != sequenceI.getDatasetSequence())
970    && (!rIsDs && tIsDs
971    && sequenceRef.getDatasetSequence() != sequenceI)
972    && (!rIsDs && !tIsDs
973    && sequenceRef.getDatasetSequence() != sequenceI
974    .getDatasetSequence())
975    && !sequenceRef.equals(sequenceI))
976    {
977    // if sequenceRef isn't intersecting with sequenceI
978    // throw away old mapping and reconstruct.
979  0 sequenceRef = null;
980  0 if (sequenceMapping != null)
981    {
982  0 sequenceMapping = null;
983    // compactAnnotationArray();
984    }
985  0 createSequenceMapping(sequenceI, 1, true);
986  0 adjustForAlignment();
987    }
988    else
989    {
990    // Mapping carried over
991  3357 sequenceRef = sequenceI;
992    }
993    }
994    else
995    {
996    // No mapping exists
997  2329 createSequenceMapping(sequenceI, 1, true);
998  2329 adjustForAlignment();
999    }
1000    }
1001    else
1002    {
1003    // throw away the mapping without compacting.
1004  63 sequenceMapping = null;
1005  63 sequenceRef = null;
1006    }
1007    }
1008   
1009    /**
1010    * @return the score
1011    */
 
1012  156 toggle public double getScore()
1013    {
1014  156 return score;
1015    }
1016   
1017    /**
1018    * @param score
1019    * the score to set
1020    */
 
1021  36131 toggle public void setScore(double score)
1022    {
1023  36131 hasScore = true;
1024  36131 this.score = score;
1025    }
1026   
1027    /**
1028    *
1029    * @return true if annotation has an associated score
1030    */
 
1031  2258 toggle public boolean hasScore()
1032    {
1033  2258 return hasScore || !Double.isNaN(score);
1034    }
1035   
1036    /**
1037    * Score only annotation
1038    *
1039    * @param label
1040    * @param description
1041    * @param score
1042    */
 
1043  34620 toggle public AlignmentAnnotation(String label, String description, double score)
1044    {
1045  34620 this(label, description, null);
1046  34620 setScore(score);
1047    }
1048   
1049    /**
1050    * copy constructor with edit based on the hidden columns marked in colSel
1051    *
1052    * @param alignmentAnnotation
1053    * @param colSel
1054    */
 
1055  18 toggle public AlignmentAnnotation(AlignmentAnnotation alignmentAnnotation,
1056    HiddenColumns hidden)
1057    {
1058  18 this(alignmentAnnotation);
1059  18 if (annotations == null)
1060    {
1061  0 return;
1062    }
1063  18 makeVisibleAnnotation(hidden);
1064    }
1065   
1066   
 
1067  0 toggle public void setPadGaps(boolean padgaps, char gapchar)
1068    {
1069  0 this.padGaps = padgaps;
1070  0 if (padgaps)
1071    {
1072  0 hasText = true;
1073  0 for (int i = 0; i < annotations.length; i++)
1074    {
1075  0 if (annotations[i] == null)
1076    {
1077  0 annotations[i] = new Annotation(String.valueOf(gapchar), null,
1078    ' ', 0f, null);
1079    }
1080  0 else if (annotations[i].displayCharacter == null
1081    || annotations[i].displayCharacter.equals(" "))
1082    {
1083  0 annotations[i].displayCharacter = String.valueOf(gapchar);
1084    }
1085    }
1086    }
1087    }
1088   
1089    /**
1090    * format description string for display
1091    *
1092    * @param seqname
1093    * @return Get the annotation description string optionally prefixed by
1094    * associated sequence name (if any)
1095    */
 
1096  10 toggle public String getDescription(boolean seqname)
1097    {
1098  10 if (seqname && this.sequenceRef != null)
1099    {
1100  3 int i = description.toLowerCase(Locale.ROOT).indexOf("<html>");
1101  3 if (i > -1)
1102    {
1103    // move the html tag to before the sequence reference.
1104  1 return "<html>" + sequenceRef.getName() + " : "
1105    + description.substring(i + 6);
1106    }
1107  2 return sequenceRef.getName() + " : " + description;
1108    }
1109  7 return description;
1110    }
1111   
 
1112  8391 toggle public boolean isValidStruc()
1113    {
1114  8391 return naStructure.isValidStruc();
1115    }
1116   
 
1117  1698553 toggle public long getInvalidStrucPos()
1118    {
1119  1698556 return naStructure.getInvalidStrucPos();
1120    }
1121   
1122    /**
1123    * machine readable ID string indicating what generated this annotation
1124    */
1125    protected String calcId = "";
1126   
1127    /**
1128    * properties associated with the calcId
1129    */
1130    protected Map<String, String> properties = new HashMap<>();
1131   
1132    /**
1133    * base colour for line graphs. If null, will be set automatically by
1134    * searching the alignment annotation
1135    */
1136    public java.awt.Color _linecolour;
1137   
 
1138  84080 toggle public String getCalcId()
1139    {
1140  84080 return calcId;
1141    }
1142   
 
1143  4057 toggle public void setCalcId(String calcId)
1144    {
1145  4057 this.calcId = calcId;
1146    }
1147   
 
1148  23231 toggle public boolean isRNA()
1149    {
1150  23231 return isrna;
1151    }
1152   
1153    /**
1154    * transfer annotation to the given sequence using the given mapping from the
1155    * current positions or an existing sequence mapping
1156    *
1157    * @param sq
1158    * @param sp2sq
1159    * map involving sq as To or From
1160    */
 
1161  222 toggle public void liftOver(SequenceI sq, Mapping sp2sq)
1162    {
1163  222 if (sp2sq.getMappedWidth() != sp2sq.getWidth())
1164    {
1165    // TODO: employ getWord/MappedWord to transfer annotation between cDNA and
1166    // Protein reference frames
1167  0 throw new Error(
1168    "liftOver currently not implemented for transfer of annotation between different types of seqeunce");
1169    }
1170  222 boolean mapIsTo = (sp2sq != null)
1171    ? (sp2sq.getTo() == sq
1172    || sp2sq.getTo() == sq.getDatasetSequence())
1173    : false;
1174   
1175    // TODO build a better annotation element map and get rid of annotations[]
1176  222 Map<Integer, Annotation> mapForsq = new HashMap<>();
1177  222 if (sequenceMapping != null)
1178    {
1179  222 if (sp2sq != null)
1180    {
1181  222 for (Entry<Integer, Annotation> ie : sequenceMapping.entrySet())
1182    {
1183  18032 Integer mpos = Integer
1184  18032 .valueOf(mapIsTo ? sp2sq.getMappedPosition(ie.getKey())
1185    : sp2sq.getPosition(ie.getKey()));
1186  18032 if (mpos >= sq.getStart() && mpos <= sq.getEnd())
1187    {
1188  18026 mapForsq.put(mpos, ie.getValue());
1189    }
1190    }
1191  222 sequenceMapping = mapForsq;
1192  222 sequenceRef = sq;
1193  222 adjustForAlignment();
1194    }
1195    else
1196    {
1197    // trim positions
1198    }
1199    }
1200    }
1201   
1202    /**
1203    * like liftOver but more general.
1204    *
1205    * Takes an array of int pairs that will be used to update the internal
1206    * sequenceMapping and so shuffle the annotated positions
1207    *
1208    * @param newref
1209    * - new sequence reference for the annotation row - if null,
1210    * sequenceRef is left unchanged
1211    * @param mapping
1212    * array of ints containing corresponding positions
1213    * @param from
1214    * - column for current coordinate system (-1 for index+1)
1215    * @param to
1216    * - column for destination coordinate system (-1 for index+1)
1217    * @param idxoffset
1218    * - offset added to index when referencing either coordinate system
1219    * @note no checks are made as to whether from and/or to are sensible
1220    * @note caller should add the remapped annotation to newref if they have not
1221    * already
1222    */
 
1223  0 toggle public void remap(SequenceI newref, HashMap<Integer, int[]> mapping,
1224    int from, int to, int idxoffset)
1225    {
1226  0 if (mapping != null)
1227    {
1228  0 Map<Integer, Annotation> old = sequenceMapping;
1229  0 Map<Integer, Annotation> remap = new HashMap<>();
1230  0 int index = -1;
1231  0 for (int mp[] : mapping.values())
1232    {
1233  0 if (index++ < 0)
1234    {
1235  0 continue;
1236    }
1237  0 Annotation ann = null;
1238  0 if (from == -1)
1239    {
1240  0 ann = sequenceMapping.get(Integer.valueOf(idxoffset + index));
1241    }
1242    else
1243    {
1244  0 if (mp != null && mp.length > from)
1245    {
1246  0 ann = sequenceMapping.get(Integer.valueOf(mp[from]));
1247    }
1248    }
1249  0 if (ann != null)
1250    {
1251  0 if (to == -1)
1252    {
1253  0 remap.put(Integer.valueOf(idxoffset + index), ann);
1254    }
1255    else
1256    {
1257  0 if (to > -1 && to < mp.length)
1258    {
1259  0 remap.put(Integer.valueOf(mp[to]), ann);
1260    }
1261    }
1262    }
1263    }
1264  0 sequenceMapping = remap;
1265  0 old.clear();
1266  0 if (newref != null)
1267    {
1268  0 sequenceRef = newref;
1269    }
1270  0 adjustForAlignment();
1271    }
1272    }
1273   
 
1274  738592 toggle public String getProperty(String property)
1275    {
1276  738595 if (properties == null)
1277    {
1278  0 return null;
1279    }
1280  738586 return properties.get(property);
1281    }
1282   
 
1283  2003 toggle public void setProperty(String property, String value)
1284    {
1285  2003 if (properties == null)
1286    {
1287  0 properties = new HashMap<>();
1288    }
1289  2003 properties.put(property, value);
1290    }
1291   
 
1292  1162 toggle public boolean hasProperties()
1293    {
1294  1162 return properties != null && properties.size() > 0;
1295    }
1296   
 
1297  381 toggle public Collection<String> getProperties()
1298    {
1299  381 if (properties == null)
1300    {
1301  0 return Collections.emptyList();
1302    }
1303  381 return properties.keySet();
1304    }
1305   
1306    /**
1307    * Returns the Annotation for the given sequence position (base 1) if any,
1308    * else null
1309    *
1310    * @param position
1311    * @return
1312    */
 
1313  273144 toggle public Annotation getAnnotationForPosition(int position)
1314    {
1315  273159 return sequenceMapping == null ? null : sequenceMapping.get(position);
1316   
1317    }
1318   
1319    /**
1320    * Set the id to "ann" followed by a counter that increments so as to be
1321    * unique for the lifetime of the JVM
1322    */
 
1323  42374 toggle protected final void setAnnotationId()
1324    {
1325  42374 this.annotationId = ANNOTATION_ID_PREFIX + Long.toString(nextId());
1326    }
1327   
1328    /**
1329    * Returns the match for the last unmatched opening RNA helix pair symbol
1330    * preceding the given column, or '(' if nothing found to match.
1331    *
1332    * @param column
1333    * @return
1334    */
 
1335  43 toggle public String getDefaultRnaHelixSymbol(int column)
1336    {
1337  43 String result = "(";
1338  43 if (annotations == null)
1339    {
1340  1 return result;
1341    }
1342   
1343    /*
1344    * for each preceding column, if it contains an open bracket,
1345    * count whether it is still unmatched at column, if so return its pair
1346    * (likely faster than the fancy alternative using stacks)
1347    */
1348  150 for (int col = column - 1; col >= 0; col--)
1349    {
1350  142 Annotation annotation = annotations[col];
1351  142 if (annotation == null)
1352    {
1353  66 continue;
1354    }
1355  76 String displayed = annotation.displayCharacter;
1356  76 if (displayed == null || displayed.length() != 1)
1357    {
1358  0 continue;
1359    }
1360  76 char symbol = displayed.charAt(0);
1361  76 if (!Rna.isOpeningParenthesis(symbol))
1362    {
1363  24 continue;
1364    }
1365   
1366    /*
1367    * found an opening bracket symbol
1368    * count (closing-opening) symbols of this type that follow it,
1369    * up to and excluding the target column; if the count is less
1370    * than 1, the opening bracket is unmatched, so return its match
1371    */
1372  52 String closer = String
1373    .valueOf(Rna.getMatchingClosingParenthesis(symbol));
1374  52 String opener = String.valueOf(symbol);
1375  52 int count = 0;
1376  256 for (int j = col + 1; j < column; j++)
1377    {
1378  204 if (annotations[j] != null)
1379    {
1380  90 String s = annotations[j].displayCharacter;
1381  90 if (closer.equals(s))
1382    {
1383  18 count++;
1384    }
1385  72 else if (opener.equals(s))
1386    {
1387  0 count--;
1388    }
1389    }
1390    }
1391  52 if (count < 1)
1392    {
1393  34 return closer;
1394    }
1395    }
1396  8 return result;
1397    }
1398   
 
1399  42374 toggle protected static synchronized long nextId()
1400    {
1401  42374 return counter++;
1402    }
1403   
1404    /**
1405    *
1406    * @return true for rows that have a range of values in their annotation set
1407    */
 
1408  5 toggle public boolean isQuantitative()
1409    {
1410  5 return graphMin < graphMax;
1411    }
1412   
1413    /**
1414    * @return true if hasData and visible are true
1415    */
 
1416  229150 toggle public boolean isForDisplay()
1417    {
1418  229150 return hasData && visible;
1419    }
1420   
1421    /**
1422    * delete any columns in alignmentAnnotation that are hidden (including
1423    * sequence associated annotation).
1424    *
1425    * @param hiddenColumns
1426    * the set of hidden columns
1427    */
 
1428  27 toggle public void makeVisibleAnnotation(HiddenColumns hiddenColumns)
1429    {
1430  27 if (annotations != null)
1431    {
1432  25 makeVisibleAnnotation(0, annotations.length - 1, hiddenColumns);
1433    }
1434    }
1435   
1436    /**
1437    * delete any columns in alignmentAnnotation that are hidden (including
1438    * sequence associated annotation).
1439    *
1440    * @param start
1441    * remove any annotation to the right of this column
1442    * @param end
1443    * remove any annotation to the left of this column
1444    * @param hiddenColumns
1445    * the set of hidden columns
1446    */
 
1447  45 toggle public void makeVisibleAnnotation(int start, int end,
1448    HiddenColumns hiddenColumns)
1449    {
1450  45 if (annotations != null)
1451    {
1452  43 if (hiddenColumns.hasHiddenColumns())
1453    {
1454  22 removeHiddenAnnotation(start, end, hiddenColumns);
1455    }
1456    else
1457    {
1458  21 restrict(start, end);
1459    }
1460    }
1461    }
1462   
1463    /**
1464    * The actual implementation of deleting hidden annotation columns
1465    *
1466    * @param start
1467    * remove any annotation to the right of this column
1468    * @param end
1469    * remove any annotation to the left of this column
1470    * @param hiddenColumns
1471    * the set of hidden columns
1472    */
 
1473  22 toggle private void removeHiddenAnnotation(int start, int end,
1474    HiddenColumns hiddenColumns)
1475    {
1476  22 start = Math.min(Math.max(0, start), annotations.length);
1477  22 end = Math.min(Math.max(-1, end), annotations.length - 1);
1478    // mangle the alignmentAnnotation annotation array
1479  22 ArrayList<Annotation[]> annels = new ArrayList<>();
1480  22 Annotation[] els = null;
1481   
1482  22 int w = 0;
1483   
1484  22 Iterator<int[]> blocks = hiddenColumns.getVisContigsIterator(start,
1485    end + 1, false);
1486   
1487  22 int copylength;
1488  22 int annotationLength;
1489  62 while (blocks.hasNext())
1490    {
1491  40 int[] block = blocks.next();
1492  40 annotationLength = block[1] - block[0] + 1;
1493   
1494  40 if (blocks.hasNext())
1495    {
1496    // copy just the visible segment of the annotation row
1497  18 copylength = annotationLength;
1498    }
1499    else
1500    {
1501  22 if (annotationLength + block[0] <= annotations.length)
1502    {
1503    // copy just the visible segment of the annotation row
1504  22 copylength = annotationLength;
1505    }
1506    else
1507    {
1508    // copy to the end of the annotation row
1509  0 copylength = annotations.length - block[0];
1510    }
1511    }
1512   
1513  40 els = new Annotation[annotationLength];
1514  40 annels.add(els);
1515  40 System.arraycopy(annotations, block[0], els, 0, copylength);
1516  40 w += annotationLength;
1517    }
1518   
1519  22 if (w != 0)
1520    {
1521  22 annotations = new Annotation[w];
1522   
1523  22 w = 0;
1524  22 for (Annotation[] chnk : annels)
1525    {
1526  40 System.arraycopy(chnk, 0, annotations, w, chnk.length);
1527  40 w += chnk.length;
1528    }
1529    }
1530    }
1531   
 
1532  182 toggle public static Iterable<AlignmentAnnotation> findAnnotations(
1533    Iterable<AlignmentAnnotation> list, SequenceI seq, String calcId,
1534    String label)
1535    {
1536  182 ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
1537  182 for (AlignmentAnnotation ann : list)
1538    {
1539  1324 if ((calcId == null || (ann.getCalcId() != null
1540    && ann.getCalcId().equals(calcId)))
1541    && (seq == null || (ann.sequenceRef != null
1542    && ann.sequenceRef == seq))
1543    && (label == null
1544    || (ann.label != null && ann.label.equals(label))))
1545    {
1546  186 aa.add(ann);
1547    }
1548    }
1549  182 return aa;
1550    }
1551   
1552    /**
1553    * Answer true if any annotation matches the calcId passed in (if not null).
1554    *
1555    * @param list
1556    * annotation to search
1557    * @param calcId
1558    * @return
1559    */
 
1560  0 toggle public static boolean hasAnnotation(List<AlignmentAnnotation> list,
1561    String calcId)
1562    {
1563   
1564  0 if (calcId != null && !"".equals(calcId))
1565    {
1566  0 for (AlignmentAnnotation a : list)
1567    {
1568  0 if (a.getCalcId() == calcId)
1569    {
1570  0 return true;
1571    }
1572    }
1573    }
1574  0 return false;
1575    }
1576   
 
1577  539 toggle public static Iterable<AlignmentAnnotation> findAnnotation(
1578    List<AlignmentAnnotation> list, String calcId)
1579    {
1580  539 List<AlignmentAnnotation> aa = new ArrayList<>();
1581  539 if (calcId == null)
1582    {
1583  1 return aa;
1584    }
1585  538 for (AlignmentAnnotation a : list)
1586    {
1587   
1588  3484 if (a.getCalcId() == calcId || (a.getCalcId() != null
1589    && calcId != null && a.getCalcId().equals(calcId)))
1590    {
1591  554 aa.add(a);
1592    }
1593    }
1594  538 return aa;
1595    }
1596   
1597    /**
1598    * convenience method to check for the 'CONTACT_MAP_NOGROUPS' property for
1599    * this alignment annotation row
1600    *
1601    * @return true if no CONTACT_MAP_NOGROUPS property is found, or it is set to
1602    * ""
1603    */
 
1604  404 toggle public boolean isShowGroupsForContactMatrix()
1605    {
1606  404 return getProperty(AlignmentAnnotation.CONTACT_MAP_NOGROUPS) == null
1607    || "".equals(
1608    getProperty(AlignmentAnnotation.CONTACT_MAP_NOGROUPS));
1609    }
1610   
1611    /**
1612    * set the 'CONTACT_MAP_NOGROUPS' property for this alignment annotation row
1613    *
1614    * @see isShowGroupsForContactMatrix
1615    */
 
1616  2 toggle public void setShowGroupsForContactMatrix(boolean showGroups)
1617    {
1618  2 setProperty(AlignmentAnnotation.CONTACT_MAP_NOGROUPS,
1619  2 showGroups ? "" : "nogroups");
1620    }
1621   
 
1622  192379 toggle public long getNoOfSequencesIncluded()
1623    {
1624  192379 return noOfSequencesIncluded;
1625    }
1626   
 
1627  5794 toggle public void setNoOfSequencesIncluded(long noOfSequencesIncluded)
1628    {
1629  5794 this.noOfSequencesIncluded = noOfSequencesIncluded;
1630    }
1631   
 
1632  897 toggle public long getNoOfTracksIncluded()
1633    {
1634    // TODO Auto-generated method stub
1635  897 return noOfTracksIncluded;
1636    }
 
1637  2002 toggle public void setNoOfTracksIncluded(long noOfTracks)
1638    {
1639  2002 this.noOfTracksIncluded = noOfTracks;
1640    }
1641   
1642   
1643    /**
1644    * This method matches the label and calcid with the
1645    * label and calcid of the AlignmentAnnotation object
1646    */
 
1647  8370 toggle public boolean labelAndCalcIdMatches(String label, String calcId)
1648    {
1649  8370 return this.label.equalsIgnoreCase(label)
1650    && ((this.getCalcId() == null && calcId == null)
1651    || (this.getCalcId() != null && calcId != null
1652    && this.getCalcId().equals(calcId)));
1653    }
1654   
 
1655  79 toggle public void setAnnotationDetailsProperty(String annotDetails) {
1656  79 this.setProperty(ANNOTATION_DETAILS, annotDetails);
1657    }
1658   
 
1659  23 toggle public String getAnnotationDetailsProperty() {
1660  23 if(hasAnnotationDetailsProperty())
1661    {
1662  18 return this.getProperty(ANNOTATION_DETAILS);
1663    }
1664   
1665  5 return null;
1666    }
1667   
 
1668  47042 toggle public boolean hasAnnotationDetailsProperty() {
1669  47035 if(this.getProperty(ANNOTATION_DETAILS) != null
1670    && this.getProperty(ANNOTATION_DETAILS).length() > 0)
1671    {
1672  46977 return true;
1673    }
1674   
1675  58 return false;
1676    }
 
1677  18 toggle public String getLabel()
1678    {
1679  18 return label;
1680    }
1681   
 
1682  18 toggle public Annotation[] getAnnotations()
1683    {
1684  18 return annotations;
1685    }
1686   
 
1687  0 toggle public double getBitScore()
1688    {
1689  0 return bitScore;
1690    }
1691   
 
1692  0 toggle public void setBitScore(double bitScore)
1693    {
1694  0 this.bitScore = bitScore;
1695    }
1696   
 
1697  0 toggle public double getEValue()
1698    {
1699  0 return eValue;
1700    }
1701   
 
1702  0 toggle public void setEValue(double eValue)
1703    {
1704  0 this.eValue = eValue;
1705    }
1706   
 
1707  21 toggle public static AlignmentAnnotation findFirstAnnotation(
1708    Iterable<AlignmentAnnotation> alignmentAnnotation, String name,
1709    String calcId, boolean autoCalc, SequenceI seqRef,
1710    SequenceGroup groupRef)
1711    {
1712   
1713  21 for (AlignmentAnnotation annot : alignmentAnnotation)
1714    {
1715  192 if (annot.autoCalculated == autoCalc && (name.equals(annot.label))
1716    && (calcId == null || annot.getCalcId().equals(calcId))
1717    && annot.sequenceRef == seqRef && annot.groupRef == groupRef)
1718    {
1719  3 return annot;
1720    }
1721    }
1722  18 return null;
1723    }
1724   
 
1725  6910 toggle public boolean hasRNAStruc()
1726    {
1727  6910 return naStructure.hasNaStruc();
1728    }
 
1729  10025 toggle public NucStructureI getRnaStructure() {
1730  10025 return naStructure;
1731    }
 
1732  1860 toggle public String getRNAStruc()
1733    {
1734  1860 return naStructure.getRNAStruc(this);
1735    }
1736   
1737    }