From fe6b3fb39308b5c045849db2be75ba07824be776 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Tue, 7 Oct 2014 17:05:06 +0100 Subject: [PATCH] JAL-1264 wip --- resources/lang/Messages.properties | 1 + src/jalview/datamodel/Alignment.java | 35 +++++++++- src/jalview/datamodel/AlignmentI.java | 4 +- src/jalview/datamodel/AnnotatedCollectionI.java | 17 +++++ src/jalview/datamodel/SequenceGroup.java | 24 +++++++ src/jalview/gui/AlignFrame.java | 24 ------- src/jalview/gui/PopupMenu.java | 83 ++++++++++++++++++++--- 7 files changed, 153 insertions(+), 35 deletions(-) diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 50ba8ad..a4bc4b8 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -744,6 +744,7 @@ label.trim_retrieved_sequences = When the reference sequence is longer than the label.choose_annotations = Choose annotations to show or hide label.show_selected_annotations = Show selected annotation types label.hide_selected_annotations = Hide selected annotation types +label.add_reference_annotations = Add reference annotations label.find = Find error.invalid_regex = Invalid regular expression label.invalid_search = Search string invalid diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java index ad7cdd2..f19d117 100755 --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@ -20,7 +20,12 @@ */ package jalview.datamodel; -import java.util.*; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Vector; /** * Data structure to hold and manipulate a multiple sequence alignment @@ -1521,4 +1526,32 @@ public class Alignment implements AlignmentI { return dataset; } + + /** + * Returns an iterable collection of annotations on this alignment which match + * the given criteria. + */ + @Override + public Iterable findAnnotation(SequenceI datasequence, + String calcId, String label) + { + List result = new ArrayList(); + for (AlignmentAnnotation ann : annotations) + { + // only sequence-linked annotations can qualify (have a datasequence) + if (ann.sequenceRef == null) + { + continue; + } + boolean matchDatasequence = (ann.sequenceRef.getDatasetSequence() == datasequence); + final String annCalcId = ann.getCalcId(); + boolean matchCalcId = (annCalcId != null && annCalcId.equals(calcId)); + boolean matchLabel = (ann.label != null && ann.label.equals(label)); + if (matchDatasequence && matchCalcId && matchLabel) + { + result.add(ann); + } + } + return result; + } } diff --git a/src/jalview/datamodel/AlignmentI.java b/src/jalview/datamodel/AlignmentI.java index d141697..c7e30a4 100755 --- a/src/jalview/datamodel/AlignmentI.java +++ b/src/jalview/datamodel/AlignmentI.java @@ -20,7 +20,9 @@ */ package jalview.datamodel; -import java.util.*; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; /** * Data structure to hold and manipulate a multiple sequence alignment diff --git a/src/jalview/datamodel/AnnotatedCollectionI.java b/src/jalview/datamodel/AnnotatedCollectionI.java index 0b4c117..6bd4ab9 100644 --- a/src/jalview/datamodel/AnnotatedCollectionI.java +++ b/src/jalview/datamodel/AnnotatedCollectionI.java @@ -40,4 +40,21 @@ public interface AnnotatedCollectionI extends SequenceCollectionI * alignment, parent group). */ AnnotatedCollectionI getContext(); + + /** + * Return an iterable set of any annotations in the collection that match the + * provided criteria, i.e. + *
    + *
  • reference the same sequence datasequence
  • + *
  • have the same calcId (source of annotation)
  • + *
  • have the same label (type of annotation)
  • + *
+ * + * @param datasequence + * @param calcId + * @param label + * @return + */ + Iterable findAnnotation(SequenceI datasequence, + String calcId, String label); } diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index 17348c2..f8fd3ee 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -1308,4 +1308,28 @@ public class SequenceGroup implements AnnotatedCollectionI { return context; } + + @Override + public Iterable findAnnotation( + SequenceI datasequence, String calcId, String label) + { + List result = new ArrayList(); + for (AlignmentAnnotation ann : getAlignmentAnnotation()) + { + // only sequence-linked annotations can qualify (have a datasequence) + if (ann.sequenceRef == null) + { + continue; + } + boolean matchDatasequence = (ann.sequenceRef.getDatasetSequence() == datasequence); + final String annCalcId = ann.getCalcId(); + boolean matchCalcId = (annCalcId != null && annCalcId.equals(calcId)); + boolean matchLabel = (ann.label != null && ann.label.equals(label)); + if (matchDatasequence && matchCalcId && matchLabel) + { + result.add(ann); + } + } + return result; + } } diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 69af72b..5da5f1d 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -5722,30 +5722,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, } /** - * Get a list of unique annotation types for the alignment, optionally - * restricted to sequence-specific annotations. - */ - protected List getAnnotationTypes(boolean sequenceSpecificOnly) - { - // TODO move this to an AlignmentUtils class or similar - List types = new ArrayList(); - for (AlignmentAnnotation aa : alignPanel.getAlignment() - .getAlignmentAnnotation()) - { - if (sequenceSpecificOnly && aa.sequenceRef == null) - { - continue; - } - String type = aa.label; - if (!types.contains(type)) - { - types.add(type); - } - } - return types; - } - - /** * Action on selection of menu option to Show or Hide all annotations. * * @param visibile diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index 6042ab8..5f6c556 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -192,6 +192,8 @@ public class PopupMenu extends JPopupMenu JMenu hideAnnotationsMenu = new JMenu(); + JMenuItem addDatasequenceAnnotations = new JMenuItem(); + JMenuItem sequenceFeature = new JMenuItem(); JMenuItem textColour = new JMenuItem(); @@ -812,11 +814,8 @@ public class PopupMenu extends JPopupMenu showAnnotationsMenu.removeAll(); hideAnnotationsMenu.removeAll(); final List all = Arrays.asList(ALL_ANNOTATIONS); - addAnnotationTypeToShowHide(showAnnotationsMenu, - all, true, - true); - addAnnotationTypeToShowHide(hideAnnotationsMenu, all, true, - false); + addAnnotationTypeToShowHide(showAnnotationsMenu, all, true, true); + addAnnotationTypeToShowHide(hideAnnotationsMenu, all, true, false); showAnnotationsMenu.addSeparator(); hideAnnotationsMenu.addSeparator(); @@ -866,8 +865,8 @@ public class PopupMenu extends JPopupMenu */ public static void getAnnotationTypesForShowHide( List> shownTypes, List> hiddenTypes, - BitSet visibleGraphGroups, - AlignmentAnnotation[] annotations, SequenceGroup sequenceGroup) + BitSet visibleGraphGroups, AlignmentAnnotation[] annotations, + SequenceGroup sequenceGroup) { // lookup table, key = graph group, value = list of types in the group Map> groupLabels = new LinkedHashMap>(); @@ -1011,8 +1010,7 @@ public class PopupMenu extends JPopupMenu * @param doShow */ protected void showHideAnnotation_actionPerformed( - Collection types, - boolean anyType, boolean doShow) + Collection types, boolean anyType, boolean doShow) { for (AlignmentAnnotation aa : ap.getAlignment() .getAlignmentAnnotation()) @@ -1519,6 +1517,19 @@ public class PopupMenu extends JPopupMenu .getString("label.show_annotations")); hideAnnotationsMenu.setText(MessageManager .getString("label.hide_annotations")); + final List referenceAnns = getDatasequenceAnnotationsNotOnAlignment(ap.av + .getSelectionGroup()); + addDatasequenceAnnotations.setText(MessageManager + .getString("label.add_reference_annotations")); + addDatasequenceAnnotations.setEnabled(!referenceAnns.isEmpty()); + addDatasequenceAnnotations.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + addReferenceAnnotations_actionPerformed(referenceAnns); + } + }); sequenceFeature.setText(MessageManager .getString("label.create_sequence_feature")); sequenceFeature.addActionListener(new ActionListener() @@ -1567,6 +1578,7 @@ public class PopupMenu extends JPopupMenu // groupMenu.add(chooseAnnotations); groupMenu.add(showAnnotationsMenu); groupMenu.add(hideAnnotationsMenu); + groupMenu.add(addDatasequenceAnnotations); groupMenu.add(editMenu); groupMenu.add(outputMenu); groupMenu.add(sequenceFeature); @@ -1800,6 +1812,59 @@ public class PopupMenu extends JPopupMenu }); } + /** + * Get a list of any annotations on the dataset sequences in the current + * selection group that are not also on the alignment. + *

+ * The criteria for 'on the alignment' is finding an annotation that matches + * on sequenceRef.datasetSequence, calcId and label. + * + * @return + */ + protected List getDatasequenceAnnotationsNotOnAlignment( + SequenceGroup sg) + { + List result = new ArrayList(); + + for (SequenceI seq : sg.getSequences()) + { + SequenceI dataset = seq.getDatasetSequence(); + AlignmentAnnotation[] datasetAnnotations = dataset.getAnnotation(); + if (datasetAnnotations != null) + { + for (AlignmentAnnotation dsann : datasetAnnotations) + { + /* + * If the alignment has no annotation that matches this one... + */ + if (!ap.getAlignment() + .findAnnotation(dataset, dsann.getCalcId(), dsann.label) + .iterator().hasNext()) + { + /* + * ...then add it to the result list + */ + result.add(dsann); + } + } + } + } + return result; + } + + /** + * Add any annotations on the sequence dataset to the alignment (that are not + * already copied to it). + */ + protected void addReferenceAnnotations_actionPerformed( + List anns) + { + for (AlignmentAnnotation ann : anns) + { + // todo: copy, add, adjust... + } + } + protected void sequenceSelectionDetails_actionPerformed() { createSequenceDetailsReport(ap.av.getSequenceSelection()); -- 1.7.10.2