JAL-1264 wip
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 7 Oct 2014 16:05:06 +0000 (17:05 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 7 Oct 2014 16:05:06 +0000 (17:05 +0100)
resources/lang/Messages.properties
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/AnnotatedCollectionI.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/PopupMenu.java

index 50ba8ad..a4bc4b8 100644 (file)
@@ -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\r
 label.show_selected_annotations = Show selected annotation types\r
 label.hide_selected_annotations = Hide selected annotation types\r
+label.add_reference_annotations = Add reference annotations\r
 label.find = Find\r
 error.invalid_regex = Invalid regular expression\r
 label.invalid_search = Search string invalid\r
index ad7cdd2..f19d117 100755 (executable)
  */
 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<AlignmentAnnotation> findAnnotation(SequenceI datasequence,
+          String calcId, String label)
+  {
+    List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+    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;
+  }
 }
index d141697..c7e30a4 100755 (executable)
@@ -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
index 0b4c117..6bd4ab9 100644 (file)
@@ -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.
+   * <ul>
+   * <li>reference the same sequence datasequence</li>
+   * <li>have the same calcId (source of annotation)</li>
+   * <li>have the same label (type of annotation)</li>
+   * </ul>
+   * 
+   * @param datasequence
+   * @param calcId
+   * @param label
+   * @return
+   */
+  Iterable<AlignmentAnnotation> findAnnotation(SequenceI datasequence,
+          String calcId, String label);
 }
index 17348c2..f8fd3ee 100755 (executable)
@@ -1308,4 +1308,28 @@ public class SequenceGroup implements AnnotatedCollectionI
   {
     return context;
   }
+
+  @Override
+  public Iterable<AlignmentAnnotation> findAnnotation(
+          SequenceI datasequence, String calcId, String label)
+  {
+    List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+    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;
+  }
 }
index 69af72b..5da5f1d 100644 (file)
@@ -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<String> getAnnotationTypes(boolean sequenceSpecificOnly)
-  {
-    // TODO move this to an AlignmentUtils class or similar
-    List<String> types = new ArrayList<String>();
-    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
index 6042ab8..5f6c556 100644 (file)
@@ -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<String> 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<List<String>> shownTypes, List<List<String>> 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<Integer, List<String>> groupLabels = new LinkedHashMap<Integer, List<String>>();
@@ -1011,8 +1010,7 @@ public class PopupMenu extends JPopupMenu
    * @param doShow
    */
   protected void showHideAnnotation_actionPerformed(
-          Collection<String> types,
-          boolean anyType, boolean doShow)
+          Collection<String> 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<AlignmentAnnotation> 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.
+   * <p/>
+   * The criteria for 'on the alignment' is finding an annotation that matches
+   * on sequenceRef.datasetSequence, calcId and label.
+   * 
+   * @return
+   */
+  protected List<AlignmentAnnotation> getDatasequenceAnnotationsNotOnAlignment(
+          SequenceGroup sg)
+  {
+    List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+    
+    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<AlignmentAnnotation> anns)
+  {
+    for (AlignmentAnnotation ann : anns)
+    {
+      // todo: copy, add, adjust...
+    }
+  }
+
   protected void sequenceSelectionDetails_actionPerformed()
   {
     createSequenceDetailsReport(ap.av.getSequenceSelection());