action.find_next = Find next
action.file = File
action.view = View
+action.annotations = Annotations
action.change_params = Change Parameters
action.apply = Apply
action.apply_threshold_all_groups = Apply threshold to all groups
label.neighbour_blosum62 = Neighbour Joining Using BLOSUM62
label.show_annotations = Show annotations
label.hide_annotations = Hide annotations
-label.show_all_annotations = Show all annotations
-label.hide_all_annotations = Hide all annotations
+label.show_all_seq_annotations = Show sequence related
+label.hide_all_seq_annotations = Hide sequence related
+label.show_all_al_annotations = Show alignment related
+label.hide_all_al_annotations = Hide alignment related
label.hide_all = Hide all
label.add_reference_annotations = Add reference annotations
label.find_tip = Search alignment, selection or sequence ids for a subsequence (ignoring gaps).<br>Accepts regular expressions - search Help for 'regex' for details.
label.norm_consensus_logo = Normalise Consensus Logo
label.apply_all_groups = Apply to all groups
label.autocalculated_annotation = Autocalculated Annotation
+label.show_first = Show first
+label.show_last = Show last
label.min_colour = Minimum Colour
label.max_colour = Maximum Colour
label.use_original_colours = Use Original Colours
label.sort_by_score = Sort by Score
label.sort_by_density = Sort by Density
label.sequence_sort_by_density = Sequence sort by Density
+label.sort_annotations_by_sequence = Sort by sequence
+label.sort_annotations_by_label = Sort by label
label.reveal = Reveal
label.hide_columns = Hide Columns
label.load_jalview_annotations = Load Jalview Annotations or Features File
}
}
/*
- * finally add the 'composite group labels' to the appropriate lists,
- * depending on whether the group is identified as visible or hidden
+ * Finally add the 'composite group labels' to the appropriate lists,
+ * depending on whether the group is identified as visible or hidden. Don't
+ * add the same label more than once (there may be many graph groups that
+ * generate it).
*/
for (String calcId : groupLabels.keySet())
{
for (int group : groupLabels.get(calcId).keySet())
{
final List<String> groupLabel = groupLabels.get(calcId).get(group);
+ // don't want to duplicate 'same types in different order'
+ Collections.sort(groupLabel);
if (visibleGraphGroups.get(group))
{
if (!shownTypes.containsKey(calcId))
{
shownTypes.put(calcId, new ArrayList<List<String>>());
}
- shownTypes.get(calcId).add(groupLabel);
+ if (!shownTypes.get(calcId).contains(groupLabel))
+ {
+ shownTypes.get(calcId).add(groupLabel);
+ }
}
else
{
{
hiddenTypes.put(calcId, new ArrayList<List<String>>());
}
- hiddenTypes.get(calcId).add(groupLabel);
+ if (!hiddenTypes.get(calcId).contains(groupLabel))
+ {
+ hiddenTypes.get(calcId).add(groupLabel);
+ }
}
}
}
* @param anns
* @return
*/
- public static List<AlignmentAnnotation> asList(
- AlignmentAnnotation[] anns)
+ public static List<AlignmentAnnotation> asList(AlignmentAnnotation[] anns)
{
// TODO use AlignmentAnnotationI instead when it exists
return (anns == null ? Collections.<AlignmentAnnotation> emptyList()
*/
package jalview.analysis;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+
import java.util.ArrayList;
import java.util.List;
-import jalview.datamodel.SequenceI;
-import jalview.datamodel.AlignmentI;
-
/**
* grab bag of useful alignment manipulation operations Expect these to be
* refactored elsewhere at some point.
newAl.setDataset(core.getDataset());
return newAl;
}
+
+ /**
+ * Returns the index (zero-based position) of a sequence in an alignment, or
+ * -1 if not found.
+ *
+ * @param al
+ * @param seq
+ * @return
+ */
+ public static int getSequenceIndex(AlignmentI al, SequenceI seq)
+ {
+ int result = -1;
+ int pos = 0;
+ for (SequenceI alSeq : al.getSequences())
+ {
+ if (alSeq == seq)
+ {
+ result = pos;
+ break;
+ }
+ pos++;
+ }
+ return result;
+ }
}
--- /dev/null
+package jalview.analysis;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * A helper class to sort all annotations associated with an alignment in
+ * various ways.
+ *
+ * @author gmcarstairs
+ *
+ */
+public class AnnotationSorter
+{
+
+ public enum SequenceAnnotationOrder
+ {
+ SEQUENCE_AND_LABEL, LABEL_AND_SEQUENCE, NONE
+ }
+
+ private final AlignmentI alignment;
+
+ private boolean showAutocalcAbove;
+
+ /**
+ * Constructor given an alignment and the location (top or bottom) of
+ * Consensus and similar.
+ *
+ * @param alignmentI
+ * @param showAutocalculatedAbove
+ */
+ public AnnotationSorter(AlignmentI alignmentI,
+ boolean showAutocalculatedAbove)
+ {
+ this.alignment = alignmentI;
+ this.showAutocalcAbove = showAutocalculatedAbove;
+ }
+
+ /**
+ * Default comparator sorts as follows by annotation type within sequence
+ * order:
+ * <ul>
+ * <li>annotations with a reference to a sequence in the alignment are sorted
+ * on sequence ordering</li>
+ * <li>other annotations go 'at the end', with their mutual order unchanged</li>
+ * <li>within the same sequence ref, sort by label (non-case-sensitive)</li>
+ * </ul>
+ */
+ private final Comparator<? super AlignmentAnnotation> bySequenceAndLabel = new Comparator<AlignmentAnnotation>()
+ {
+ @Override
+ public int compare(AlignmentAnnotation o1, AlignmentAnnotation o2)
+ {
+ if (o1 == null && o2 == null)
+ {
+ return 0;
+ }
+ if (o1 == null)
+ {
+ return -1;
+ }
+ if (o2 == null)
+ {
+ return 1;
+ }
+
+ /*
+ * Ignore label (keep existing ordering) for
+ * Conservation/Quality/Consensus etc
+ */
+ if (o1.sequenceRef == null && o2.sequenceRef == null)
+ {
+ return 0;
+ }
+ int sequenceOrder = compareSequences(o1, o2);
+ return sequenceOrder == 0 ? compareLabels(o1, o2) : sequenceOrder;
+ }
+ };
+
+ /**
+ * This comparator sorts as follows by sequence order within annotation type
+ * <ul>
+ * <li>annotations with a reference to a sequence in the alignment are sorted
+ * on label (non-case-sensitive)</li>
+ * <li>other annotations go 'at the end', with their mutual order unchanged</li>
+ * <li>within the same label, sort by order of the related sequences</li>
+ * </ul>
+ */
+ private final Comparator<? super AlignmentAnnotation> byLabelAndSequence = new Comparator<AlignmentAnnotation>()
+ {
+ @Override
+ public int compare(AlignmentAnnotation o1, AlignmentAnnotation o2)
+ {
+ if (o1 == null && o2 == null)
+ {
+ return 0;
+ }
+ if (o1 == null)
+ {
+ return -1;
+ }
+ if (o2 == null)
+ {
+ return 1;
+ }
+
+ /*
+ * Ignore label (keep existing ordering) for
+ * Conservation/Quality/Consensus etc
+ */
+ if (o1.sequenceRef == null && o2.sequenceRef == null)
+ {
+ return 0;
+ }
+
+ /*
+ * Sort non-sequence-related before or after sequence-related.
+ */
+ if (o1.sequenceRef == null)
+ {
+ return showAutocalcAbove ? -1 : 1;
+ }
+ if (o2.sequenceRef == null)
+ {
+ return showAutocalcAbove ? 1 : -1;
+ }
+ int labelOrder = compareLabels(o1, o2);
+ return labelOrder == 0 ? compareSequences(o1, o2) : labelOrder;
+ }
+ };
+
+ /**
+ * noSort leaves sort order unchanged, within sequence- and
+ * non-sequence-related annotations, but may switch the ordering of these
+ * groups. Note this is guaranteed (at least in Java 7) as Arrays.sort() is
+ * guaranteed to be 'stable' (not change ordering of equal items).
+ */
+ private Comparator<? super AlignmentAnnotation> noSort = new Comparator<AlignmentAnnotation>()
+ {
+ @Override
+ public int compare(AlignmentAnnotation o1, AlignmentAnnotation o2)
+ {
+ if (o1 != null && o2 != null)
+ {
+ if (o1.sequenceRef == null && o2.sequenceRef != null)
+ {
+ return showAutocalcAbove ? -1 : 1;
+ }
+ if (o1.sequenceRef != null && o2.sequenceRef == null)
+ {
+ return showAutocalcAbove ? 1 : -1;
+ }
+ }
+ return 0;
+ }
+ };
+
+ /**
+ * Sort by the specified ordering of sequence-specific annotations.
+ *
+ * @param alignmentAnnotations
+ * @param order
+ */
+ public void sort(AlignmentAnnotation[] alignmentAnnotations,
+ SequenceAnnotationOrder order)
+ {
+ Comparator<? super AlignmentAnnotation> comparator = getComparator(order);
+
+ if (alignmentAnnotations != null)
+ {
+ synchronized (alignmentAnnotations)
+ {
+ Arrays.sort(alignmentAnnotations, comparator);
+ }
+ }
+ }
+
+ /**
+ * Get the comparator for the specified sort order.
+ *
+ * @param order
+ * @return
+ */
+ private Comparator<? super AlignmentAnnotation> getComparator(
+ SequenceAnnotationOrder order)
+ {
+ if (order == null)
+ {
+ return noSort;
+ }
+ switch (order)
+ {
+ case NONE:
+ return this.noSort;
+ case SEQUENCE_AND_LABEL:
+ return this.bySequenceAndLabel;
+ case LABEL_AND_SEQUENCE:
+ return this.byLabelAndSequence;
+ default:
+ throw new UnsupportedOperationException(order.toString());
+ }
+ }
+
+ /**
+ * Non-case-sensitive comparison of annotation labels. Returns zero if either
+ * argument is null.
+ *
+ * @param o1
+ * @param o2
+ * @return
+ */
+ private int compareLabels(AlignmentAnnotation o1, AlignmentAnnotation o2)
+ {
+ if (o1 == null || o2 == null)
+ {
+ return 0;
+ }
+ String label1 = o1.label;
+ String label2 = o2.label;
+ if (label1 == null && label2 == null)
+ {
+ return 0;
+ }
+ if (label1 == null)
+ {
+ return -1;
+ }
+ if (label2 == null)
+ {
+ return 1;
+ }
+ return label1.toUpperCase().compareTo(label2.toUpperCase());
+ }
+
+ /**
+ * Comparison based on position of associated sequence (if any) in the
+ * alignment. Returns zero if either argument is null.
+ *
+ * @param o1
+ * @param o2
+ * @return
+ */
+ private int compareSequences(AlignmentAnnotation o1,
+ AlignmentAnnotation o2)
+ {
+ SequenceI seq1 = o1.sequenceRef;
+ SequenceI seq2 = o2.sequenceRef;
+ if (seq1 == null && seq2 == null)
+ {
+ return 0;
+ }
+ /*
+ * Sort non-sequence-related before or after sequence-related.
+ */
+ if (seq1 == null)
+ {
+ return showAutocalcAbove ? -1 : 1;
+ }
+ if (seq2 == null)
+ {
+ return showAutocalcAbove ? 1 : -1;
+ }
+ // get sequence index - but note -1 means 'at end' so needs special handling
+ int index1 = AlignmentUtils.getSequenceIndex(alignment, seq1);
+ int index2 = AlignmentUtils.getSequenceIndex(alignment, seq2);
+ if (index1 == index2)
+ {
+ return 0;
+ }
+ if (index1 == -1)
+ {
+ return -1;
+ }
+ if (index2 == -1)
+ {
+ return 1;
+ }
+ return Integer.compare(index1, index2);
+ }
+}
import jalview.ws.dbsources.das.datamodel.DasSourceRegistry;
import java.awt.Color;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.Date;
+import java.util.Properties;
-import org.apache.log4j.*;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.SimpleLayout;
/**
* Stores and retrieves Jalview Application Properties Lists and fields within
* <li>SHOW_QUALITY show alignment quality annotation</li>
* <li>SHOW_ANNOTATIONS show alignment annotation rows</li>
* <li>SHOW_CONSERVATION show alignment conservation annotation</li>
+ * <li>SORT_ANNOTATIONS currently either SEQUENCE_AND_LABEL or
+ * LABEL_AND_SEQUENCE</li>
+ * <li>SHOW_AUTOCALC_ABOVE true to show autocalculated annotations above
+ * sequence annotations</li>
* <li>CENTRE_COLUMN_LABELS centre the labels at each column in a displayed
* annotation row</li>
* <li>DEFAULT_COLOUR default colour scheme to apply for a new alignment</li>
if (log != null)
{
if (re != null)
+ {
log.debug("Caught runtime exception in googletracker init:", re);
+ }
if (ex != null)
+ {
log.warn(
"Failed to initialise GoogleTracker for Jalview Desktop with version "
+ vrs, ex);
+ }
if (err != null)
+ {
log.error(
"Whilst initing GoogleTracker for Jalview Desktop version "
+ vrs, err);
+ }
}
else
{
}
/**
- * Make a new AlignFrame from exisiting alignmentPanels
+ * Make a new AlignFrame from existing alignmentPanels
*
* @param ap
* AlignmentPanel
scaleRight.setVisible(av.wrapAlignment);
annotationPanelMenuItem.setState(av.showAnnotation);
/*
- * Show/hide all annotations only enabled if annotation panel is shown
+ * Show/hide annotations only enabled if annotation panel is shown
*/
- showAllAnnotations.setEnabled(annotationPanelMenuItem.getState());
- hideAllAnnotations.setEnabled(annotationPanelMenuItem.getState());
+ showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
+ hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
+ showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
+ hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
viewBoxesMenuItem.setSelected(av.showBoxes);
viewTextMenuItem.setSelected(av.showText);
showNonconservedMenuItem.setSelected(av.getShowUnconserved());
final boolean setVisible = annotationPanelMenuItem.isSelected();
viewport.setShowAnnotation(setVisible);
alignPanel.setAnnotationVisible(setVisible);
- this.showAllAnnotations.setEnabled(setVisible);
- this.hideAllAnnotations.setEnabled(setVisible);
+ this.showAllSeqAnnotations.setEnabled(setVisible);
+ this.hideAllSeqAnnotations.setEnabled(setVisible);
+ this.showAllAlAnnotations.setEnabled(setVisible);
+ this.hideAllAlAnnotations.setEnabled(setVisible);
}
@Override
}
/**
- * Action on selection of menu option to Show or Hide all annotations.
+ * Action on selection of menu options to Show or Hide annotations.
*
- * @param visibile
+ * @param visible
+ * @param forSequences
+ * update sequence-related annotations
+ * @param forAlignment
+ * update non-sequence-related annotations
*/
@Override
- protected void setAllAnnotationsVisibility(boolean visible)
+ protected void setAnnotationsVisibility(boolean visible,
+ boolean forSequences, boolean forAlignment)
{
for (AlignmentAnnotation aa : alignPanel.getAlignment()
.getAlignmentAnnotation())
{
- aa.visible = visible;
+ boolean apply = (aa.sequenceRef == null && forAlignment)
+ || (aa.sequenceRef != null && forSequences);
+ if (apply)
+ {
+ aa.visible = visible;
+ }
}
this.alignPanel.paintAlignment(true);
}
+
+ /**
+ * Store selected annotation sort order for the view and repaint.
+ */
+ @Override
+ protected void sortAnnotations_actionPerformed()
+ {
+ this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
+ this.alignPanel.av
+ .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
+ alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
+ }
}
class PrintThread extends Thread
*/
package jalview.gui;
+import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.analysis.NJTree;
import jalview.api.AlignViewportI;
import jalview.bin.Cache;
boolean showAnnotation = true;
+ SequenceAnnotationOrder sortAnnotationsBy = null;
+
int charHeight;
int charWidth;
}
}
- wrapAlignment = jalview.bin.Cache.getDefault("WRAP_ALIGNMENT", false);
- showUnconserved = jalview.bin.Cache.getDefault("SHOW_UNCONSERVED",
- false);
- sortByTree = jalview.bin.Cache.getDefault("SORT_BY_TREE", false);
- followSelection = jalview.bin.Cache.getDefault("FOLLOW_SELECTIONS",
- true);
+ wrapAlignment = Cache.getDefault("WRAP_ALIGNMENT", false);
+ showUnconserved = Cache.getDefault("SHOW_UNCONSERVED", false);
+ sortByTree = Cache.getDefault("SORT_BY_TREE", false);
+ followSelection = Cache.getDefault("FOLLOW_SELECTIONS", true);
+ sortAnnotationsBy = SequenceAnnotationOrder.valueOf(Cache.getDefault(
+ "SORT_ANNOTATIONS", SequenceAnnotationOrder.NONE.name()));
+ showAutocalculatedAbove = Cache
+ .getDefault("SHOW_AUTOCALC_ABOVE", false);
}
/**
{
// TODO: JAL-1126
if (historyList == null || redoList == null)
+ {
return new long[]
{ -1, -1 };
+ }
return new long[]
{ historyList.hashCode(), this.redoList.hashCode() };
}
Vector pdbs = alignment.getSequenceAt(i).getDatasetSequence()
.getPDBId();
if (pdbs == null)
+ {
continue;
+ }
SequenceI sq;
for (int p = 0; p < pdbs.size(); p++)
{
if (p1.getId().equals(pdb.getId()))
{
if (!seqs.contains(sq = alignment.getSequenceAt(i)))
+ {
seqs.add(sq);
+ }
continue;
}
private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<String, AutoCalcSetting>();
+ private boolean showAutocalculatedAbove;
+
public AutoCalcSetting getCalcIdSettingsFor(String calcId)
{
return calcIdParams.get(calcId);
Cache.log.debug("trigger update for " + calcId);
}
}
+
+ protected SequenceAnnotationOrder getSortAnnotationsBy()
+ {
+ return sortAnnotationsBy;
+ }
+
+ protected void setSortAnnotationsBy(SequenceAnnotationOrder sortAnnotationsBy)
+ {
+ this.sortAnnotationsBy = sortAnnotationsBy;
+ }
+
+ protected boolean isShowAutocalculatedAbove()
+ {
+ return showAutocalculatedAbove;
+ }
+
+ protected void setShowAutocalculatedAbove(boolean showAutocalculatedAbove)
+ {
+ this.showAutocalculatedAbove = showAutocalculatedAbove;
+ }
}
*/
package jalview.gui;
-import java.beans.*;
-import java.io.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.awt.print.*;
-import javax.swing.*;
-
+import jalview.analysis.AnnotationSorter;
import jalview.api.AlignmentViewPanel;
import jalview.bin.Cache;
-import jalview.datamodel.*;
-import jalview.jbgui.*;
-import jalview.schemes.*;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.jbgui.GAlignmentPanel;
+import jalview.schemes.ResidueProperties;
import jalview.structure.StructureSelectionManager;
import jalview.util.MessageManager;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+
+import javax.swing.SwingUtilities;
+
/**
* DOCUMENT ME!
*
int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
int maxwidth = Math.max(20,
- Math.min(afwidth - 200, (int) 2 * afwidth / 3));
+ Math.min(afwidth - 200, 2 * afwidth / 3));
return calculateIdWidth(maxwidth);
}
}
}
+ /**
+ * Repaint the alignment including the annotations and overview panels (if
+ * shown).
+ */
public void paintAlignment(boolean updateOverview)
{
+ final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
+ av.isShowAutocalculatedAbove());
+ sorter.sort(getAlignment()
+ .getAlignmentAnnotation(),
+ av.getSortAnnotationsBy());
repaint();
if (updateOverview)
// / How many sequences and residues can we fit on a printable page?
int totalRes = (pwidth - idWidth) / av.getCharWidth();
- int totalSeq = (int) ((pheight - scaleHeight) / av.getCharHeight()) - 1;
+ int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1;
int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
int offset = -alabels.scrollOffset;
pg.translate(0, offset);
pg.translate(-idWidth - 3, (endSeq - startSeq) * av.charHeight + 3);
- alabels.drawComponent((Graphics2D) pg, idWidth);
+ alabels.drawComponent(pg, idWidth);
pg.translate(idWidth + 3, 0);
annotationPanel.renderer.drawComponent(annotationPanel, av,
- (Graphics2D) pg, -1, startRes, endRes + 1);
+ pg, -1, startRes, endRes + 1);
pg.translate(0, -offset);
}
* Add annotations at the top of the annotation, in the same order as their
* related sequences.
*/
- int insertPosition = 0;
for (SequenceI seq : candidates.keySet())
{
for (AlignmentAnnotation ann : candidates.get(seq))
// adjust for gaps
copyAnn.adjustForAlignment();
// add to the alignment and set visible
- this.ap.getAlignment().addAnnotation(copyAnn, insertPosition++);
+ this.ap.getAlignment().addAnnotation(copyAnn);
copyAnn.visible = true;
}
}
*/
package jalview.jbgui;
+import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.bin.Cache;
import jalview.gui.JvSwingUtils;
import jalview.schemes.ColourSchemeProperty;
protected JMenu viewMenu = new JMenu();
+ protected JMenu annotationsMenu = new JMenu();
+
protected JMenu colourMenu = new JMenu();
protected JMenu calculateMenu = new JMenu();
JMenuItem showAllhidden = new JMenuItem();
- protected JMenuItem showAllAnnotations = new JMenuItem();
+ protected JMenuItem showAllSeqAnnotations = new JMenuItem();
+
+ protected JMenuItem hideAllSeqAnnotations = new JMenuItem();
+
+ protected JMenuItem showAllAlAnnotations = new JMenuItem();
+
+ protected JMenuItem hideAllAlAnnotations = new JMenuItem();
+
+ protected JCheckBoxMenuItem sortAnnBySequence = new JCheckBoxMenuItem();
- protected JMenuItem hideAllAnnotations = new JMenuItem();
+ protected JCheckBoxMenuItem sortAnnByLabel = new JCheckBoxMenuItem();
protected JCheckBoxMenuItem hiddenMarkers = new JCheckBoxMenuItem();
protected JCheckBoxMenuItem applyAutoAnnotationSettings = new JCheckBoxMenuItem();
+ protected JCheckBoxMenuItem showAutoFirst = new JCheckBoxMenuItem();
+
+ protected JCheckBoxMenuItem showAutoLast = new JCheckBoxMenuItem();
+
private JMenuItem grpsFromSelection = new JMenuItem();
+ private SequenceAnnotationOrder annotationSortOrder;
+
+ private boolean showAutoCalculatedAbove = false;
+
public GAlignFrame()
{
try
});
editMenu.setText(MessageManager.getString("action.edit"));
viewMenu.setText(MessageManager.getString("action.view"));
+ annotationsMenu.setText(MessageManager.getString("action.annotations"));
colourMenu.setText(MessageManager.getString("action.colour"));
calculateMenu.setText(MessageManager.getString("action.calculate"));
webService.setText(MessageManager.getString("action.web_service"));
annotationPanelMenuItem_actionPerformed(e);
}
});
- /*
- * Show/hide all annotations only enabled if annotation panel is shown
- */
- showAllAnnotations.setText(MessageManager
- .getString("label.show_all_annotations"));
- showAllAnnotations.setEnabled(annotationPanelMenuItem.getState());
- showAllAnnotations.addActionListener(new ActionListener()
+ showAllAlAnnotations.setText(MessageManager
+ .getString("label.show_all_al_annotations"));
+ final boolean isAnnotationPanelShown = annotationPanelMenuItem
+ .getState();
+ showAllAlAnnotations.setEnabled(isAnnotationPanelShown);
+ showAllAlAnnotations.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ showAllAnnotations_actionPerformed(false, true);
+ }
+ });
+ hideAllAlAnnotations.setText(MessageManager
+ .getString("label.hide_all_al_annotations"));
+ hideAllAlAnnotations.setEnabled(isAnnotationPanelShown);
+ hideAllAlAnnotations.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ hideAllAnnotations_actionPerformed(false, true);
+ }
+ });
+ showAllSeqAnnotations.setText(MessageManager
+ .getString("label.show_all_seq_annotations"));
+ showAllSeqAnnotations.setEnabled(isAnnotationPanelShown);
+ showAllSeqAnnotations.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ showAllAnnotations_actionPerformed(true, false);
+ }
+ });
+ hideAllSeqAnnotations.setText(MessageManager
+ .getString("label.hide_all_seq_annotations"));
+ hideAllSeqAnnotations.setEnabled(isAnnotationPanelShown);
+ hideAllSeqAnnotations.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ hideAllAnnotations_actionPerformed(true, false);
+ }
+ });
+ sortAnnBySequence.setText(MessageManager
+ .getString("label.sort_annotations_by_sequence"));
+ sortAnnBySequence.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- showAllAnnotations_actionPerformed();
+ boolean newState = sortAnnBySequence.getState();
+ sortAnnByLabel.setState(false);
+ setAnnotationSortOrder(newState ? SequenceAnnotationOrder.SEQUENCE_AND_LABEL
+ : SequenceAnnotationOrder.NONE);
+ sortAnnotations_actionPerformed();
}
});
- hideAllAnnotations.setText(MessageManager
- .getString("label.hide_all_annotations"));
- hideAllAnnotations.setEnabled(annotationPanelMenuItem.getState());
- hideAllAnnotations.addActionListener(new ActionListener()
+ sortAnnByLabel.setText(MessageManager
+ .getString("label.sort_annotations_by_label"));
+ sortAnnByLabel.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- hideAllAnnotations_actionPerformed();
+ boolean newState = sortAnnByLabel.getState();
+ sortAnnBySequence.setState(false);
+ setAnnotationSortOrder(newState ? SequenceAnnotationOrder.LABEL_AND_SEQUENCE
+ : SequenceAnnotationOrder.NONE);
+ sortAnnotations_actionPerformed();
}
});
colourTextMenuItem.setText(MessageManager
applyAutoAnnotationSettings.setVisible(true);
applyAutoAnnotationSettings.addActionListener(new ActionListener()
{
-
@Override
public void actionPerformed(ActionEvent e)
{
applyAutoAnnotationSettings_actionPerformed(e);
}
+ });
+ showAutoFirst.setText(MessageManager.getString("label.show_first"));
+ showAutoFirst.setState(Cache.getDefault("SHOW_AUTOCALC_ABOVE", false));
+ showAutoFirst.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ boolean sortFirst = showAutoFirst.getState();
+ setShowAutoCalculatedAbove(sortFirst);
+ showAutoLast.setState(!sortFirst);
+ sortAnnotations_actionPerformed();
+ }
+ });
+ showAutoLast.setText(MessageManager.getString("label.show_last"));
+ showAutoLast.setState(!showAutoFirst.getState());
+ showAutoLast.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ boolean sortLast = showAutoLast.getState();
+ setShowAutoCalculatedAbove(!sortLast);
+ showAutoFirst.setState(!sortLast);
+ sortAnnotations_actionPerformed();
+ }
});
nucleotideColour.setText(MessageManager.getString("label.nucleotide"));
alignFrameMenuBar.add(editMenu);
alignFrameMenuBar.add(selectMenu);
alignFrameMenuBar.add(viewMenu);
+ alignFrameMenuBar.add(annotationsMenu);
alignFrameMenuBar.add(formatMenu);
alignFrameMenuBar.add(colourMenu);
alignFrameMenuBar.add(calculateMenu);
viewMenu.add(hideMenu);
viewMenu.addSeparator();
viewMenu.add(followHighlightMenuItem);
- viewMenu.add(annotationPanelMenuItem);
- viewMenu.add(showAllAnnotations);
- viewMenu.add(hideAllAnnotations);
+ annotationsMenu.add(annotationPanelMenuItem);
+ annotationsMenu.addSeparator();
+ annotationsMenu.add(showAllAlAnnotations);
+ annotationsMenu.add(hideAllAlAnnotations);
+ annotationsMenu.addSeparator();
+ annotationsMenu.add(showAllSeqAnnotations);
+ annotationsMenu.add(hideAllSeqAnnotations);
+ annotationsMenu.add(sortAnnBySequence);
+ annotationsMenu.add(sortAnnByLabel);
+ annotationsMenu.addSeparator();
+ autoAnnMenu.add(showAutoFirst);
+ autoAnnMenu.add(showAutoLast);
+ autoAnnMenu.addSeparator();
autoAnnMenu.add(applyAutoAnnotationSettings);
autoAnnMenu.add(showConsensusHistogram);
autoAnnMenu.add(showSequenceLogo);
autoAnnMenu.addSeparator();
autoAnnMenu.add(showGroupConservation);
autoAnnMenu.add(showGroupConsensus);
- viewMenu.add(autoAnnMenu);
+ annotationsMenu.add(autoAnnMenu);
viewMenu.addSeparator();
viewMenu.add(showSeqFeatures);
// viewMenu.add(showSeqFeaturesHeight);
}
/**
+ * Action on clicking sort annotations by type.
+ *
+ * @param sortOrder
+ */
+ protected void sortAnnotations_actionPerformed()
+ {
+ }
+
+ /**
* Action on clicking Show all annotations.
+ *
+ * @param forSequences
+ * update sequence-related annotations
+ * @param forAlignment
+ * update non-sequence-related annotations
*/
- protected void showAllAnnotations_actionPerformed()
+ protected void showAllAnnotations_actionPerformed(boolean forSequences,
+ boolean forAlignment)
{
- setAllAnnotationsVisibility(true);
+ setAnnotationsVisibility(true, forSequences, forAlignment);
}
/**
* Action on clicking Hide all annotations.
+ *
+ * @param forSequences
+ * update sequence-related annotations
+ * @param forAlignment
+ * update non-sequence-related annotations
*/
- protected void hideAllAnnotations_actionPerformed()
+ protected void hideAllAnnotations_actionPerformed(boolean forSequences,
+ boolean forAlignment)
{
- setAllAnnotationsVisibility(false);
+ setAnnotationsVisibility(false, forSequences, forAlignment);
}
/**
- * Set the visibility of all annotations to true or false.
+ * Set the visibility of annotations to true or false. Can act on
+ * sequence-related annotations, or alignment-related, or both.
*
* @param visible
+ * @param forSequences
+ * update sequence-related annotations
+ * @param forAlignment
+ * update non-sequence-related annotations
*/
- protected void setAllAnnotationsVisibility(boolean visible)
+ protected void setAnnotationsVisibility(boolean visible,
+ boolean forSequences, boolean forAlignment)
{
}
// TODO Auto-generated method stub
}
+
+ protected boolean isShowAutoCalculatedAbove()
+ {
+ return showAutoCalculatedAbove;
+ }
+
+ protected void setShowAutoCalculatedAbove(boolean showAutoCalculatedAbove)
+ {
+ this.showAutoCalculatedAbove = showAutoCalculatedAbove;
+ }
+
+ protected SequenceAnnotationOrder getAnnotationSortOrder()
+ {
+ return annotationSortOrder;
+ }
+
+ protected void setAnnotationSortOrder(SequenceAnnotationOrder annotationSortOrder)
+ {
+ this.annotationSortOrder = annotationSortOrder;
+ }
}
"TIETHKEEELTA-" + EOL;
// @formatter:on
- private static final int SEQ_ANN_COUNT = 10;
+ private static final int SEQ_ANN_COUNT = 12;
private AlignmentI alignment;
@Test
public void testGetShownHiddenTypes_withGraphGroups()
{
+ final int GROUP_3 = 3;
final int GROUP_4 = 4;
final int GROUP_5 = 5;
final int GROUP_6 = 6;
SequenceI[] seqs = alignment.getSequencesArray();
/*
- * Configure annotation properties for test
+ * Annotations for selection group and graph group
+ *
+ * Hidden annotations Label2, Label3, in (hidden) group 5
*/
- // annotations for selection group and graph group
- // hidden annotations Label2, Label3, in (hidden) group 5
anns[2].sequenceRef = seqs[3];
anns[2].visible = false;
anns[2].graph = AlignmentAnnotation.LINE_GRAPH;
anns[3].graphGroup = GROUP_5;
// need to ensure annotations have the same calcId as well
anns[3].setCalcId("CalcId2");
+ // annotations for a different hidden group generating the same group label
+ anns[10].sequenceRef = seqs[0];
+ anns[10].visible = false;
+ anns[10].graph = AlignmentAnnotation.LINE_GRAPH;
+ anns[10].graphGroup = GROUP_3;
+ anns[10].label = "Label3";
+ anns[10].setCalcId("CalcId2");
+ anns[11].sequenceRef = seqs[3];
+ anns[11].visible = false;
+ anns[11].graph = AlignmentAnnotation.LINE_GRAPH;
+ anns[11].graphGroup = GROUP_3;
+ anns[11].label = "Label2";
+ anns[11].setCalcId("CalcId2");
// annotations Label1 (hidden), Label5 (visible) in group 6 (visible)
anns[1].sequenceRef = seqs[3];
anns[5].graph = AlignmentAnnotation.LINE_GRAPH;
anns[5].graphGroup = GROUP_6;
anns[5].setCalcId("CalcId1");
+ /*
+ * Annotations 0 and 4 are visible, for a different CalcId and graph group.
+ * They produce the same label as annotations 1 and 5, which should not be
+ * duplicated in the results. This case corresponds to (e.g.) many
+ * occurrences of an IUPred Short/Long annotation group, one per sequence.
+ */
+ anns[4].sequenceRef = seqs[0];
+ anns[4].visible = false;
+ anns[4].graph = AlignmentAnnotation.LINE_GRAPH;
+ anns[4].graphGroup = GROUP_4;
+ anns[4].label = "Label1";
+ anns[4].setCalcId("CalcId1");
+ anns[0].sequenceRef = seqs[0];
+ anns[0].visible = true;
+ anns[0].graph = AlignmentAnnotation.LINE_GRAPH;
+ anns[0].graphGroup = GROUP_4;
+ anns[0].label = "Label5";
+ anns[0].setCalcId("CalcId1");
- // annotations outwith selection group - should be ignored
- // hidden grouped annotations
+ /*
+ * Annotations outwith selection group - should be ignored.
+ */
+ // Hidden grouped annotations
anns[6].sequenceRef = seqs[2];
anns[6].visible = false;
anns[6].graph = AlignmentAnnotation.LINE_GRAPH;
anns[8].visible = false;
anns[8].graph = AlignmentAnnotation.LINE_GRAPH;
anns[8].graphGroup = GROUP_4;
+
// visible grouped annotations Label7, Label9
anns[7].sequenceRef = seqs[2];
anns[7].visible = true;
consoleDebug(shownTypes, hiddenTypes);
- // CalcId1 / Label1, Label5 (only) should be 'shown', as a compound type
+ // CalcId1 / Label1, Label5 (only) should be 'shown', once, as a compound
+ // type
+ assertEquals(1, shownTypes.size());
assertEquals(1, shownTypes.get("CalcId1").size());
assertEquals(2, shownTypes.get("CalcId1").get(0).size());
assertEquals("Label1", shownTypes.get("CalcId1").get(0).get(0));
assertEquals("Label5", shownTypes.get("CalcId1").get(0).get(1));
// CalcId2 / Label2, Label3 (only) should be 'hidden'
+ assertEquals(1, hiddenTypes.size());
assertEquals(1, hiddenTypes.get("CalcId2").size());
assertEquals(2, hiddenTypes.get("CalcId2").get(0).size());
assertEquals("Label2", hiddenTypes.get("CalcId2").get(0).get(0));
--- /dev/null
+package jalview.analysis;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class AnnotationSorterTest
+{
+ private static final int NUM_SEQS = 6;
+
+ private static final int NUM_ANNS = 7;
+
+ private static final String SS = "secondary structure";
+
+ AlignmentAnnotation[] anns = new AlignmentAnnotation[0];
+
+ Alignment al = null;
+
+ /*
+ * Set up 6 sequences and 7 annotations.
+ */
+ @Before
+ public void setUp()
+ {
+ al = buildAlignment(NUM_SEQS);
+ anns = buildAnnotations(NUM_ANNS);
+ }
+
+ /**
+ * Construct an array of numAnns annotations
+ *
+ * @param numAnns
+ *
+ * @return
+ */
+ protected AlignmentAnnotation[] buildAnnotations(int numAnns)
+ {
+ List<AlignmentAnnotation> annlist = new ArrayList<AlignmentAnnotation>();
+ for (int i = 0; i < numAnns; i++)
+ {
+ AlignmentAnnotation ann = new AlignmentAnnotation(SS + i, "", 0);
+ annlist.add(ann);
+ }
+ return annlist.toArray(anns);
+ }
+
+ /**
+ * Make an alignment with numSeqs sequences in it.
+ *
+ * @param numSeqs
+ *
+ * @return
+ */
+ private Alignment buildAlignment(int numSeqs)
+ {
+ SequenceI[] seqs = new Sequence[numSeqs];
+ for (int i = 0; i < numSeqs; i++)
+ {
+ seqs[i] = new Sequence("Sequence" + i, "axrdkfp");
+ }
+ return new Alignment(seqs);
+ }
+
+ /**
+ * Test sorting by annotation type (label) within sequence order, including
+ * <ul>
+ * <li>annotations with no sequence reference - sort to end keeping mutual
+ * ordering</li>
+ * <li>annotations with sequence ref = sort in sequence order</li>
+ * <li>multiple annotations for same sequence ref - sort by label
+ * non-case-specific</li>
+ * <li>annotations with reference to sequence not in alignment - treat like no
+ * sequence ref</li>
+ * </ul>
+ */
+ @Test
+ public void testSortBySequenceAndType_autocalcLast()
+ {
+ // @formatter:off
+ anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
+ anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
+ anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
+ anns[3].sequenceRef = null; anns[3].label = "Quality";
+ anns[4].sequenceRef = null; anns[4].label = "Consensus";
+ anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "label5";
+ anns[6].sequenceRef = al.getSequenceAt(3); anns[6].label = "IRP";
+ // @formatter:on
+
+ AnnotationSorter testee = new AnnotationSorter(al, false);
+ testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
+ assertEquals("label5", anns[0].label); // for sequence 0
+ assertEquals("label0", anns[1].label); // for sequence 1
+ assertEquals("iron", anns[2].label); // sequence 3 /iron
+ assertEquals("IRP", anns[3].label); // sequence 3/IRP
+ assertEquals("structure", anns[4].label); // sequence 3/structure
+ assertEquals("Quality", anns[5].label); // non-sequence annotations
+ assertEquals("Consensus", anns[6].label); // retain ordering
+ }
+
+ /**
+ * Variant with autocalculated annotations sorting to front
+ */
+ @Test
+ public void testSortBySequenceAndType_autocalcFirst()
+ {
+ // @formatter:off
+ anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
+ anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
+ anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
+ anns[3].sequenceRef = null; anns[3].label = "Quality";
+ anns[4].sequenceRef = null; anns[4].label = "Consensus";
+ anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "label5";
+ anns[6].sequenceRef = al.getSequenceAt(3); anns[6].label = "IRP";
+ // @formatter:on
+
+ AnnotationSorter testee = new AnnotationSorter(al, true);
+ testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
+ assertEquals("Quality", anns[0].label); // non-sequence annotations
+ assertEquals("Consensus", anns[1].label); // retain ordering
+ assertEquals("label5", anns[2].label); // for sequence 0
+ assertEquals("label0", anns[3].label); // for sequence 1
+ assertEquals("iron", anns[4].label); // sequence 3 /iron
+ assertEquals("IRP", anns[5].label); // sequence 3/IRP
+ assertEquals("structure", anns[6].label); // sequence 3/structure
+ }
+
+ /**
+ * Test sorting by annotation type (label) within sequence order, including
+ * <ul>
+ * <li>annotations with no sequence reference - sort to end keeping mutual
+ * ordering</li>
+ * <li>annotations with sequence ref = sort in sequence order</li>
+ * <li>multiple annotations for same sequence ref - sort by label
+ * non-case-specific</li>
+ * <li>annotations with reference to sequence not in alignment - treat like no
+ * sequence ref</li>
+ * </ul>
+ */
+ @Test
+ public void testSortByTypeAndSequence_autocalcLast()
+ {
+ // @formatter:off
+ anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
+ anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
+ anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
+ anns[3].sequenceRef = null; anns[3].label = "Quality";
+ anns[4].sequenceRef = null; anns[4].label = "Consensus";
+ anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "IRON";
+ anns[6].sequenceRef = al.getSequenceAt(2); anns[6].label = "Structure";
+ // @formatter:on
+
+ AnnotationSorter testee = new AnnotationSorter(al, false);
+ testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+ assertEquals("IRON", anns[0].label); // IRON / sequence 0
+ assertEquals("iron", anns[1].label); // iron / sequence 3
+ assertEquals("label0", anns[2].label); // label0 / sequence 1
+ assertEquals("Structure", anns[3].label); // Structure / sequence 2
+ assertEquals("structure", anns[4].label); // structure / sequence 3
+ assertEquals("Quality", anns[5].label); // non-sequence annotations
+ assertEquals("Consensus", anns[6].label); // retain ordering
+ }
+
+ /**
+ * Variant of test with autocalculated annotations sorted to front
+ */
+ @Test
+ public void testSortByTypeAndSequence_autocalcFirst()
+ {
+ // @formatter:off
+ anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
+ anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
+ anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
+ anns[3].sequenceRef = null; anns[3].label = "Quality";
+ anns[4].sequenceRef = null; anns[4].label = "Consensus";
+ anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "IRON";
+ anns[6].sequenceRef = al.getSequenceAt(2); anns[6].label = "Structure";
+ // @formatter:on
+
+ AnnotationSorter testee = new AnnotationSorter(al, true);
+ testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+ assertEquals("Quality", anns[0].label); // non-sequence annotations
+ assertEquals("Consensus", anns[1].label); // retain ordering
+ assertEquals("IRON", anns[2].label); // IRON / sequence 0
+ assertEquals("iron", anns[3].label); // iron / sequence 3
+ assertEquals("label0", anns[4].label); // label0 / sequence 1
+ assertEquals("Structure", anns[5].label); // Structure / sequence 2
+ assertEquals("structure", anns[6].label); // structure / sequence 3
+ }
+
+ /**
+ * Variant of test with autocalculated annotations sorted to front but
+ * otherwise no change.
+ */
+ @Test
+ public void testNoSort_autocalcFirst()
+ {
+ // @formatter:off
+ anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
+ anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
+ anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
+ anns[3].sequenceRef = null; anns[3].label = "Quality";
+ anns[4].sequenceRef = null; anns[4].label = "Consensus";
+ anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "IRON";
+ anns[6].sequenceRef = al.getSequenceAt(2); anns[6].label = "Structure";
+ // @formatter:on
+
+ AnnotationSorter testee = new AnnotationSorter(al, true);
+ testee.sort(anns, SequenceAnnotationOrder.NONE);
+ assertEquals("Quality", anns[0].label); // non-sequence annotations
+ assertEquals("Consensus", anns[1].label); // retain ordering
+ assertEquals("label0", anns[2].label);
+ assertEquals("structure", anns[3].label);
+ assertEquals("iron", anns[4].label);
+ assertEquals("IRON", anns[5].label);
+ assertEquals("Structure", anns[6].label);
+ }
+
+ @Test
+ public void testSort_timingPresorted()
+ {
+ final long targetTime = 100; // ms
+ final int numSeqs = 10000;
+ final int numAnns = 20000;
+ al = buildAlignment(numSeqs);
+ anns = buildAnnotations(numAnns);
+
+ /*
+ * Set the annotations presorted by label
+ */
+ Random r = new Random();
+ final SequenceI[] sequences = al.getSequencesArray();
+ for (int i = 0; i < anns.length; i++)
+ {
+ SequenceI randomSequenceRef = sequences[r.nextInt(sequences.length)];
+ anns[i].sequenceRef = randomSequenceRef;
+ anns[i].label = "label" + i;
+ }
+ long startTime = System.currentTimeMillis();
+ AnnotationSorter testee = new AnnotationSorter(al, false);
+ testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+ long endTime = System.currentTimeMillis();
+ final long elapsed = endTime - startTime;
+ System.out.println("Timing test for presorted " + numSeqs
+ + " sequences and "
+ + numAnns + " annotations took " + elapsed + "ms");
+ assertTrue("Sort took more than " + targetTime + "ms",
+ elapsed <= targetTime);
+ }
+
+ /**
+ * Timing test for sorting randomly sorted annotations
+ */
+ @Test
+ public void testSort_timingUnsorted()
+ {
+ final int numSeqs = 2000;
+ final int numAnns = 4000;
+ al = buildAlignment(numSeqs);
+ anns = buildAnnotations(numAnns);
+
+ /*
+ * Set the annotations in random order with respect to the sequences
+ */
+ Random r = new Random();
+ final SequenceI[] sequences = al.getSequencesArray();
+ for (int i = 0; i < anns.length; i++)
+ {
+ SequenceI randomSequenceRef = sequences[r.nextInt(sequences.length)];
+ anns[i].sequenceRef = randomSequenceRef;
+ anns[i].label = "label" + i;
+ }
+ long startTime = System.currentTimeMillis();
+ AnnotationSorter testee = new AnnotationSorter(al, false);
+ testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
+ long endTime = System.currentTimeMillis();
+ final long elapsed = endTime - startTime;
+ System.out.println("Timing test for unsorted " + numSeqs
+ + " sequences and "
+ + numAnns + " annotations took " + elapsed + "ms");
+ }
+
+ /**
+ * Timing test for sorting annotations with a limited range of types (labels).
+ */
+ @Test
+ public void testSort_timingSemisorted()
+ {
+ final int numSeqs = 2000;
+ final int numAnns = 4000;
+ al = buildAlignment(numSeqs);
+ anns = buildAnnotations(numAnns);
+
+ String[] labels = new String[]
+ { "label1", "label2", "label3", "label4", "label5", "label6" };
+
+ /*
+ * Set the annotations in sequence order with randomly assigned labels.
+ */
+ Random r = new Random();
+ final SequenceI[] sequences = al.getSequencesArray();
+ for (int i = 0; i < anns.length; i++)
+ {
+ SequenceI sequenceRef = sequences[i % sequences.length];
+ anns[i].sequenceRef = sequenceRef;
+ anns[i].label = labels[r.nextInt(labels.length)];
+ }
+ long startTime = System.currentTimeMillis();
+ AnnotationSorter testee = new AnnotationSorter(al, false);
+ testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+ long endTime = System.currentTimeMillis();
+ long elapsed = endTime - startTime;
+ System.out.println("Sort by type for semisorted " + numSeqs
+ + " sequences and "
+ + numAnns + " annotations took " + elapsed + "ms");
+
+ // now resort by sequence
+ startTime = System.currentTimeMillis();
+ testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
+ endTime = System.currentTimeMillis();
+ elapsed = endTime - startTime;
+ System.out.println("Resort by sequence for semisorted " + numSeqs
+ + " sequences and " + numAnns + " annotations took " + elapsed
+ + "ms");
+
+ // now resort by type
+ startTime = System.currentTimeMillis();
+ testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
+ endTime = System.currentTimeMillis();
+ elapsed = endTime - startTime;
+ System.out.println("Resort by type for semisorted " + numSeqs
+ + " sequences and " + numAnns + " annotations took " + elapsed
+ + "ms");
+ }
+}