2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.analysis;
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.SequenceI;
25 import jalview.renderer.AnnotationRenderer;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.BitSet;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.List;
35 public class AlignmentAnnotationUtils
39 * Helper method to populate lists of annotation types for the Show/Hide
40 * Annotations menus. If sequenceGroup is not null, this is restricted to
41 * annotations which are associated with sequences in the selection group.
43 * If an annotation row is currently visible, its type (label) is added (once
44 * only per type), to the shownTypes list. If it is currently hidden, it is
45 * added to the hiddenTypesList.
47 * For rows that belong to a line graph group, so are always rendered
50 * <li>Treat all rows in the group as visible, if at least one of them is</li>
51 * <li>Build a list of all the annotation types that belong to the group</li>
55 * a map, keyed by calcId (annotation source), whose entries are the
56 * lists of annotation types found for the calcId; each annotation
57 * type in turn may be a list (in the case of grouped annotations)
59 * a map, similar to shownTypes, but for hidden annotation types
61 * the annotations on the alignment to scan
63 * the sequences to restrict search to
65 public static void getShownHiddenTypes(
66 Map<String, List<List<String>>> shownTypes,
67 Map<String, List<List<String>>> hiddenTypes,
68 List<AlignmentAnnotation> annotations,
69 List<SequenceI> forSequences)
71 BitSet visibleGraphGroups = AlignmentAnnotationUtils
72 .getVisibleLineGraphGroups(annotations);
75 * Build a lookup, by calcId (annotation source), of all annotation types in
78 Map<String, Map<Integer, List<String>>> groupLabels = new HashMap<String, Map<Integer, List<String>>>();
80 // trackers for which calcId!label combinations we have dealt with
81 List<String> addedToShown = new ArrayList<String>();
82 List<String> addedToHidden = new ArrayList<String>();
84 for (AlignmentAnnotation aa : annotations)
87 * Ignore non-positional annotations, can't render these against an
90 if (aa.annotations == null)
94 if (forSequences != null && (aa.sequenceRef != null
95 && forSequences.contains(aa.sequenceRef)))
97 String calcId = aa.getCalcId();
100 * Build a 'composite label' for types in line graph groups.
102 final List<String> labelAsList = new ArrayList<String>();
103 final String displayLabel = aa.label;
104 labelAsList.add(displayLabel);
105 if (aa.graph == AlignmentAnnotation.LINE_GRAPH
106 && aa.graphGroup > -1)
108 if (!groupLabels.containsKey(calcId))
110 groupLabels.put(calcId, new HashMap<Integer, List<String>>());
112 Map<Integer, List<String>> groupLabelsForCalcId = groupLabels
114 if (groupLabelsForCalcId.containsKey(aa.graphGroup))
116 if (!groupLabelsForCalcId.get(aa.graphGroup)
117 .contains(displayLabel))
119 groupLabelsForCalcId.get(aa.graphGroup).add(displayLabel);
124 groupLabelsForCalcId.put(aa.graphGroup, labelAsList);
129 * 'Simple case' - not a grouped annotation type - list of one label
133 String rememberAs = calcId + "!" + displayLabel;
134 if (aa.visible && !addedToShown.contains(rememberAs))
136 if (!shownTypes.containsKey(calcId))
138 shownTypes.put(calcId, new ArrayList<List<String>>());
140 shownTypes.get(calcId).add(labelAsList);
141 addedToShown.add(rememberAs);
145 if (!aa.visible && !addedToHidden.contains(rememberAs))
147 if (!hiddenTypes.containsKey(calcId))
149 hiddenTypes.put(calcId, new ArrayList<List<String>>());
151 hiddenTypes.get(calcId).add(labelAsList);
152 addedToHidden.add(rememberAs);
159 * Finally add the 'composite group labels' to the appropriate lists,
160 * depending on whether the group is identified as visible or hidden. Don't
161 * add the same label more than once (there may be many graph groups that
164 for (String calcId : groupLabels.keySet())
166 for (int group : groupLabels.get(calcId).keySet())
168 final List<String> groupLabel = groupLabels.get(calcId).get(group);
169 // don't want to duplicate 'same types in different order'
170 Collections.sort(groupLabel);
171 if (visibleGraphGroups.get(group))
173 if (!shownTypes.containsKey(calcId))
175 shownTypes.put(calcId, new ArrayList<List<String>>());
177 if (!shownTypes.get(calcId).contains(groupLabel))
179 shownTypes.get(calcId).add(groupLabel);
184 if (!hiddenTypes.containsKey(calcId))
186 hiddenTypes.put(calcId, new ArrayList<List<String>>());
188 if (!hiddenTypes.get(calcId).contains(groupLabel))
190 hiddenTypes.get(calcId).add(groupLabel);
198 * Returns a BitSet (possibly empty) of those graphGroups for line graph
199 * annotations, which have at least one member annotation row marked visible.
201 * Only one row in each visible group is marked visible, but when it is drawn,
202 * so are all the other rows in the same group.
204 * This lookup set allows us to check whether rows apparently marked not
205 * visible are in fact shown.
207 * @see AnnotationRenderer#drawComponent
211 public static BitSet getVisibleLineGraphGroups(
212 List<AlignmentAnnotation> annotations)
214 BitSet result = new BitSet();
215 for (AlignmentAnnotation ann : annotations)
217 if (ann.graph == AlignmentAnnotation.LINE_GRAPH && ann.visible)
219 int gg = ann.graphGroup;
230 * Converts an array of AlignmentAnnotation into a List of
231 * AlignmentAnnotation. A null array is converted to an empty list.
236 public static List<AlignmentAnnotation> asList(AlignmentAnnotation[] anns)
238 // TODO use AlignmentAnnotationI instead when it exists
239 return (anns == null ? Collections.<AlignmentAnnotation> emptyList()
240 : Arrays.asList(anns));