JAL-2016 FeatureSettingsI now FeatureSettingsModelI
[jalview.git] / src / jalview / gui / AlignFrame.java
index 85f7d19..5438ce8 100644 (file)
@@ -32,6 +32,7 @@ import jalview.api.AlignViewControllerI;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureSettingsControllerI;
+import jalview.api.FeatureSettingsModelI;
 import jalview.api.SplitContainerI;
 import jalview.api.ViewStyleI;
 import jalview.api.analysis.ScoreModelI;
@@ -53,6 +54,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.DBRefSource;
 import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SeqCigar;
@@ -94,9 +96,11 @@ import jalview.schemes.ZappoColourScheme;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
+import jalview.ws.SequenceFetcher;
 import jalview.ws.jws1.Discoverer;
 import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.seqfetcher.ASequenceFetcher;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
 import java.awt.BorderLayout;
@@ -904,7 +908,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     rnahelicesColour.setEnabled(av.getAlignment().hasRNAStructure());
     rnahelicesColour
             .setSelected(av.getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
-    setShowProductsEnabled();
+
+    showProducts.setEnabled(canShowProducts());
+
     updateEditMenuBar();
   }
 
@@ -960,7 +966,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void fetchSequence_actionPerformed(ActionEvent e)
   {
-    new SequenceFetcher(this);
+    new jalview.gui.SequenceFetcher(this);
   }
 
   @Override
@@ -4652,67 +4658,27 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
-  /*
-   * public void vamsasStore_actionPerformed(ActionEvent e) { JalviewFileChooser
-   * chooser = new JalviewFileChooser(jalview.bin.Cache.
-   * getProperty("LAST_DIRECTORY"));
-   * 
-   * chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle("Export
-   * to Vamsas file"); chooser.setToolTipText("Export");
-   * 
-   * int value = chooser.showSaveDialog(this);
-   * 
-   * if (value == JalviewFileChooser.APPROVE_OPTION) {
-   * jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);
-   * //vs.store(chooser.getSelectedFile().getAbsolutePath() ); vs.storeJalview(
-   * chooser.getSelectedFile().getAbsolutePath(), this); } }
-   */
   /**
-   * prototype of an automatically enabled/disabled analysis function
+   * Searches selected sequences for xRef products and builds the Show
+   * Cross-References menu (formerly called Show Products)
    * 
+   * @return true if Show Cross-references menu should be enabled.
    */
-  protected void setShowProductsEnabled()
+  public boolean canShowProducts()
   {
     SequenceI[] selection = viewport.getSequenceSelection();
-    if (canShowProducts(selection, viewport.getSelectionGroup() != null,
-            viewport.getAlignment().getDataset()))
-    {
-      showProducts.setEnabled(true);
-
-    }
-    else
-    {
-      showProducts.setEnabled(false);
-    }
-  }
-
-  /**
-   * search selection for sequence xRef products and build the show products
-   * menu.
-   * 
-   * @param selection
-   * @param dataset
-   * @return true if showProducts menu should be enabled.
-   */
-  public boolean canShowProducts(SequenceI[] selection,
-          boolean isRegionSelection, Alignment dataset)
-  {
+    AlignmentI dataset = viewport.getAlignment().getDataset();
     boolean showp = false;
     try
     {
       showProducts.removeAll();
       final boolean dna = viewport.getAlignment().isNucleotide();
-      final Alignment ds = dataset;
       String[] ptypes = (selection == null || selection.length == 0) ? null
               : CrossRef.findSequenceXrefTypes(dna, selection, dataset);
-      // Object[] prods =
-      // CrossRef.buildXProductsList(viewport.getAlignment().isNucleotide(),
-      // selection, dataset, true);
-      final SequenceI[] sel = selection;
+
       for (int t = 0; ptypes != null && t < ptypes.length; t++)
       {
         showp = true;
-        final boolean isRegSel = isRegionSelection;
         final AlignFrame af = this;
         final String source = ptypes[t];
         JMenuItem xtype = new JMenuItem(ptypes[t]);
@@ -4722,9 +4688,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           @Override
           public void actionPerformed(ActionEvent e)
           {
-            // TODO: new thread for this call with vis-delay
-            af.showProductsFor(af.viewport.getSequenceSelection(),
-                    isRegSel, dna, source);
+            showProductsFor(af.viewport.getSequenceSelection(), dna, source);
           }
 
         });
@@ -4735,15 +4699,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     } catch (Exception e)
     {
       jalview.bin.Cache.log
-              .warn("canTranslate threw an exception - please report to help@jalview.org",
+              .warn("canShowProducts threw an exception - please report to help@jalview.org",
                       e);
       return false;
     }
     return showp;
   }
 
-  protected void showProductsFor(final SequenceI[] sel,
-          final boolean isRegSel, final boolean dna, final String source)
+  protected void showProductsFor(final SequenceI[] sel, final boolean dna,
+          final String source)
   {
     Runnable foo = new Runnable()
     {
@@ -4757,44 +4721,42 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 new Object[] { source }), sttime);
         try
         {
-          // update our local dataset reference
-          Alignment ds = AlignFrame.this.getViewport().getAlignment()
-                  .getDataset();
-          Alignment prods = CrossRef
-                  .findXrefSequences(sel, dna, source, ds);
-          if (prods != null)
+          /*
+           * 'peer' sequences are any to add to this alignment, for example
+           * alternative protein products for my protein's gene
+           */
+          List<SequenceI> addedPeers = new ArrayList<SequenceI>();
+          AlignmentI alignment = AlignFrame.this.getViewport()
+                  .getAlignment();
+          Alignment xrefs = CrossRef.findXrefSequences(sel, dna, source,
+                  alignment, addedPeers);
+          if (xrefs != null)
           {
-            SequenceI[] sprods = new SequenceI[prods.getHeight()];
-            for (int s = 0; s < sprods.length; s++)
+            /*
+             * figure out colour scheme if any to apply to features
+             */
+            ASequenceFetcher sftch = new SequenceFetcher();
+            List<DbSourceProxy> proxies = sftch.getSourceProxy(source);
+            FeatureSettingsModelI featureColourScheme = null;
+            for (DbSourceProxy proxy : proxies)
             {
-              sprods[s] = (prods.getSequenceAt(s)).deriveSequence();
-              if (ds.getSequences() == null
-                      || !ds.getSequences().contains(
-                              sprods[s].getDatasetSequence()))
+              FeatureSettingsModelI preferredColours = proxy
+                      .getFeatureColourScheme();
+              if (preferredColours != null)
               {
-                ds.addSequence(sprods[s].getDatasetSequence());
+                featureColourScheme = preferredColours;
+                break;
               }
-              sprods[s].updatePDBIds();
             }
-            Alignment al = new Alignment(sprods);
-            al.setDataset(ds);
+            Alignment al = makeCrossReferencesAlignment(
+                    alignment.getDataset(), xrefs);
 
-            /*
-             * Copy dna-to-protein mappings to new alignment
-             */
-            // TODO 1: no mappings are set up for EMBL product
-            // TODO 2: if they were, should add them to protein alignment, not
-            // dna
-            List<AlignedCodonFrame> cf = prods.getCodonFrames();
-            for (AlignedCodonFrame acf : cf)
-            {
-              al.addCodonFrame(acf);
-            }
             AlignFrame newFrame = new AlignFrame(al, DEFAULT_WIDTH,
                     DEFAULT_HEIGHT);
-            String newtitle = "" + (dna ? "Proteins" : "Nucleotides")
-                    + " for " + (isRegSel ? "selected region of " : "")
-                    + getTitle();
+            String newtitle = String.format("%s %s %s",
+                    MessageManager.getString(dna ? "label.proteins"
+                            : "label.nucleotides"), MessageManager
+                            .getString("label.for"), getTitle());
             newFrame.setTitle(newtitle);
 
             boolean asSplitFrame = Cache.getDefault(
@@ -4808,47 +4770,102 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               AlignmentI copyAlignment = null;
               final SequenceI[] sequenceSelection = AlignFrame.this.viewport
                       .getSequenceSelection();
+              List<AlignedCodonFrame> cf = xrefs.getCodonFrames();
               if (dna)
               {
                 copyAlignment = AlignmentUtils.makeCdsAlignment(
-                        sequenceSelection, cf);
+                        sequenceSelection, cf, alignment);
+                if (copyAlignment.getHeight() == 0)
+                {
+                  System.err.println("Failed to make CDS alignment");
+                }
                 al.getCodonFrames().clear();
                 al.getCodonFrames().addAll(cf);
-                final StructureSelectionManager ssm = StructureSelectionManager
-                        .getStructureSelectionManager(Desktop.instance);
-                ssm.registerMappings(cf);
               }
               else
               {
                 copyAlignment = new Alignment(new Alignment(
                         sequenceSelection));
+                copyAlignment.getCodonFrames().addAll(cf);
               }
-              AlignFrame copyThis = new AlignFrame(copyAlignment,
-                      AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
-              copyThis.setTitle(AlignFrame.this.getTitle());
-              // SplitFrame with dna above, protein below
-              boolean showSequenceFeatures = viewport
-                      .isShowSequenceFeatures();
-              newFrame.setShowSeqFeatures(showSequenceFeatures);
-              copyThis.setShowSeqFeatures(showSequenceFeatures);
-              FeatureRenderer myFeatureStyling = alignPanel.getSeqPanel().seqCanvas
-                      .getFeatureRenderer();
+              copyAlignment.setGapCharacter(AlignFrame.this.viewport
+                      .getGapCharacter());
+              StructureSelectionManager ssm = StructureSelectionManager
+                      .getStructureSelectionManager(Desktop.instance);
+              ssm.registerMappings(cf);
+
               /*
-               * copy feature rendering settings to split frame
+               * add in any extra 'peer' sequences discovered
+               * (e.g. alternative protein products)
                */
-              newFrame.alignPanel.getSeqPanel().seqCanvas
-                      .getFeatureRenderer().transferSettings(
-                              myFeatureStyling);
-              copyThis.alignPanel.getSeqPanel().seqCanvas
-                      .getFeatureRenderer().transferSettings(
-                              myFeatureStyling);
-              SplitFrame sf = new SplitFrame(dna ? copyThis : newFrame,
-                      dna ? newFrame : copyThis);
-              newFrame.setVisible(true);
-              copyThis.setVisible(true);
-              String linkedTitle = MessageManager
-                      .getString("label.linked_view_title");
-              Desktop.addInternalFrame(sf, linkedTitle, -1, -1);
+              for (SequenceI peer : addedPeers)
+              {
+                copyAlignment.addSequence(peer);
+              }
+
+              if (copyAlignment.getHeight() > 0)
+              {
+                /*
+                 * align protein to dna
+                 */
+                // FIXME what if the dna is not aligned :-O
+                if (dna)
+                {
+                  al.alignAs(copyAlignment);
+                }
+                else
+                {
+                  /*
+                   * align cdna to protein - currently only if 
+                   * fetching and aligning Ensembl transcripts!
+                   */
+                  if (DBRefSource.ENSEMBL.equalsIgnoreCase(source))
+                  {
+                    copyAlignment.alignAs(al);
+                  }
+                }
+
+                AlignFrame copyThis = new AlignFrame(copyAlignment,
+                        AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+                copyThis.setTitle(AlignFrame.this.getTitle());
+
+                boolean showSequenceFeatures = viewport
+                        .isShowSequenceFeatures();
+                newFrame.setShowSeqFeatures(showSequenceFeatures);
+                copyThis.setShowSeqFeatures(showSequenceFeatures);
+                FeatureRenderer myFeatureStyling = alignPanel.getSeqPanel().seqCanvas
+                        .getFeatureRenderer();
+
+                /*
+                 * copy feature rendering settings to split frame
+                 */
+                newFrame.alignPanel.getSeqPanel().seqCanvas
+                        .getFeatureRenderer().transferSettings(
+                                myFeatureStyling);
+                copyThis.alignPanel.getSeqPanel().seqCanvas
+                        .getFeatureRenderer().transferSettings(
+                                myFeatureStyling);
+
+                /*
+                 * apply 'database source' feature configuration
+                 * if any was found
+                 */
+                // TODO is this the feature colouring for the original
+                // alignment or the fetched xrefs? either could be Ensembl
+                newFrame.getViewport().applyFeaturesStyle(
+                        featureColourScheme);
+                copyThis.getViewport().applyFeaturesStyle(
+                        featureColourScheme);
+
+                SplitFrame sf = new SplitFrame(dna ? copyThis : newFrame,
+                        dna ? newFrame : copyThis);
+                newFrame.setVisible(true);
+                copyThis.setVisible(true);
+                String linkedTitle = MessageManager
+                        .getString("label.linked_view_title");
+                Desktop.addInternalFrame(sf, linkedTitle, -1, -1);
+                sf.adjustDivider();
+              }
             }
             else
             {
@@ -4878,6 +4895,35 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 new Object[] { source }), sttime);
       }
 
+      /**
+       * Makes an alignment containing the given sequences; the sequences are
+       * added to the given alignment dataset, and the dataset is set on (shared
+       * by) the new alignment
+       * 
+       * @param dataset
+       * @param seqs
+       * @return
+       */
+      protected Alignment makeCrossReferencesAlignment(Alignment dataset,
+              Alignment seqs)
+      {
+        SequenceI[] sprods = new SequenceI[seqs.getHeight()];
+        for (int s = 0; s < sprods.length; s++)
+        {
+          sprods[s] = (seqs.getSequenceAt(s)).deriveSequence();
+          if (dataset.getSequences() == null
+                  || !dataset.getSequences().contains(
+                          sprods[s].getDatasetSequence()))
+          {
+            dataset.addSequence(sprods[s].getDatasetSequence());
+          }
+          sprods[s].updatePDBIds();
+        }
+        Alignment al = new Alignment(sprods);
+        al.setDataset(dataset);
+        return al;
+      }
+
     };
     Thread frunner = new Thread(foo);
     frunner.start();
@@ -5314,10 +5360,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               alignPanel.paintAlignment(true);
             }
           }
-            else
-            {
-              new FileLoader().LoadFile(viewport, file, protocol, format);
-            }
+          else
+          {
+            new FileLoader().LoadFile(viewport, file, protocol, format);
+          }
         }
       }
       if (isAnnotation)
@@ -5525,14 +5571,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           @Override
           public void run()
           {
-            boolean isNuclueotide = alignPanel.alignFrame
-                    .getViewport().getAlignment()
-                    .isNucleotide();
+            boolean isNuclueotide = alignPanel.alignFrame.getViewport()
+                    .getAlignment().isNucleotide();
             new jalview.ws.DBRefFetcher(alignPanel.av
-                    .getSequenceSelection(),
-                    alignPanel.alignFrame, null,
-                    alignPanel.alignFrame.featureSettings,
-                    isNuclueotide)
+                    .getSequenceSelection(), alignPanel.alignFrame, null,
+                    alignPanel.alignFrame.featureSettings, isNuclueotide)
                     .fetchDBRefs(false);
           }
         }).start();
@@ -5547,7 +5590,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       @Override
       public void run()
       {
-        final jalview.ws.SequenceFetcher sf = SequenceFetcher
+        final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
                 .getSequenceFetcherSingleton(me);
         javax.swing.SwingUtilities.invokeLater(new Runnable()
         {
@@ -5608,8 +5651,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                                 .getSequenceSelection(),
                                 alignPanel.alignFrame, dassource,
                                 alignPanel.alignFrame.featureSettings,
-                                isNuclueotide)
-                                .fetchDBRefs(false);
+                                isNuclueotide).fetchDBRefs(false);
                       }
                     }).start();
                   }
@@ -5649,8 +5691,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                                 .getSequenceSelection(),
                                 alignPanel.alignFrame, dassource,
                                 alignPanel.alignFrame.featureSettings,
-                                isNuclueotide)
-                                .fetchDBRefs(false);
+                                isNuclueotide).fetchDBRefs(false);
                       }
                     }).start();
                   }
@@ -5705,8 +5746,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                                   .getSequenceSelection(),
                                   alignPanel.alignFrame, dassrc,
                                   alignPanel.alignFrame.featureSettings,
-                                  isNuclueotide)
-                                  .fetchDBRefs(false);
+                                  isNuclueotide).fetchDBRefs(false);
                         }
                       }).start();
                     }