added SeqSearch service interface. Documented and refactored web service client ...
[jalview.git] / src / jalview / gui / AlignFrame.java
index c7887da..39a7fac 100755 (executable)
@@ -59,11 +59,17 @@ public class AlignFrame
   Vector alignPanels = new Vector();
 
 
-  /** DOCUMENT ME!! */
+  /** 
+   * Last format used to load or save alignments in this window 
+   */
   String currentFileFormat = null;
-
+  /**
+   * Current filename for this alignment
+   */
   String fileName = null;
 
+  
+
 
   /**
    * Creates a new AlignFrame object.
@@ -156,7 +162,12 @@ public class AlignFrame
    addKeyListener();
 
   }
-
+  /**
+   * Change the filename and format for the alignment, and
+   * enable the 'reload' button functionality.
+   * @param file valid filename
+   * @param format format of file
+   */
   public void setFileName(String file, String format)
   {
      fileName = file;
@@ -498,14 +509,17 @@ public class AlignFrame
     showTranslation.setVisible( nucleotide );
     conservationMenuItem.setEnabled( !nucleotide );
     modifyConservation.setEnabled(   !nucleotide );
-
+    
     //Remember AlignFrame always starts as protein
     if(!nucleotide)
     {
       calculateMenu.remove(calculateMenu.getItemCount()-2);
     }
+    setShowProductsEnabled();
   }
 
+
+
   /**
    * Need to call this method when tabs are selected for multiple views,
    * or when loading from Jalview2XML.java
@@ -519,6 +533,7 @@ public class AlignFrame
     conservationMenuItem.setSelected(av.getConservationSelected());
     seqLimits.setSelected(av.getShowJVSuffix());
     idRightAlign.setSelected(av.rightAlignIds);
+    centreColumnLabelsMenuItem.setState(av.centreColumnLabels);
     renderGapsMenuItem.setSelected(av.renderGaps);
     wrapMenuItem.setSelected(av.wrapAlignment);
     scaleAbove.setVisible(av.wrapAlignment);
@@ -580,10 +595,18 @@ public class AlignFrame
 
     validate();
   }
-
-
-
-
+  /**
+   * 
+   * @return true if any progress bars are still active
+   */
+  public boolean operationInProgress()
+  {
+    if (progressBars!=null && progressBars.size()>0)
+    {
+      return true;
+    }
+    return false;
+  }
   /*
    Added so Castor Mapping file can obtain Jalview Version
   */
@@ -668,7 +691,7 @@ public class AlignFrame
   public void save_actionPerformed(ActionEvent e)
   {
     if(fileName==null
-       || currentFileFormat==null
+       || (currentFileFormat==null || jalview.io.AppletFormatAdapter.isValidFormat(currentFileFormat, true))
        || fileName.startsWith("http")
         )
     {
@@ -689,10 +712,8 @@ public class AlignFrame
   {
     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
         getProperty( "LAST_DIRECTORY"),
-        new String[]
-        { "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc","jar" },
-        new String[]
-        { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview" },
+        jalview.io.AppletFormatAdapter.WRITABLE_EXTENSIONS,
+        jalview.io.AppletFormatAdapter.WRITABLE_FNAMES,
         currentFileFormat,
         false);
 
@@ -722,7 +743,10 @@ public class AlignFrame
                                     currentFileFormat);
 
       jalview.bin.Cache.setProperty("LAST_DIRECTORY", fileName);
-
+      if (currentFileFormat.indexOf(" ")>-1)
+      {
+        currentFileFormat = currentFileFormat.substring(0, currentFileFormat.indexOf(" "));
+      }
       saveAlignment(fileName, currentFileFormat);
     }
   }
@@ -749,8 +773,18 @@ public class AlignFrame
 
     }
     else
-    {
-
+    {        
+      if (!jalview.io.AppletFormatAdapter.isValidFormat(format, true))
+      {
+        // JBPNote need to have a raise_gui flag here
+        JOptionPane.showInternalMessageDialog(
+                this, "Cannot save file " + fileName + " using format "+format,
+                "Alignment output format not supported",
+                JOptionPane.WARNING_MESSAGE);
+        saveAs_actionPerformed(null);
+        return false;
+      }
+        
       String[] omitHidden = null;
 
       if (viewport.hasHiddenColumns)
@@ -766,11 +800,11 @@ public class AlignFrame
           omitHidden = viewport.getViewAsString(false);
       }
       }
-
-      String output = new FormatAdapter().formatSequences(
+      FormatAdapter f = new FormatAdapter();
+      String output = f.formatSequences(
           format,
-          viewport.alignment.getSequencesArray(),
-          omitHidden);
+          (Alignment) viewport.alignment, // class cast exceptions will occur in the distant future
+          omitHidden, f.getCacheSuffixDefault(format), viewport.colSel);
 
       if (output == null)
       {
@@ -841,8 +875,8 @@ public class AlignFrame
 
     cap.setText(new FormatAdapter().formatSequences(
         e.getActionCommand(),
-        viewport.alignment.getSequencesArray(),
-        omitHidden));
+        viewport.alignment,
+        omitHidden, viewport.colSel));
   }
 
   /**
@@ -1425,9 +1459,9 @@ public class AlignFrame
   }
 
   /**
-   * DOCUMENT ME!
+   * Paste contents of Jalview clipboard
    *
-   * @param newAlignment DOCUMENT ME!
+   * @param newAlignment true to paste to a new alignment, otherwise add to this.
    */
   void paste(boolean newAlignment)
   {
@@ -2156,6 +2190,12 @@ public class AlignFrame
     alignPanel.paintAlignment(true);
   }
 
+  public void centreColumnLabels_actionPerformed(ActionEvent e)
+  {
+    viewport.centreColumnLabels = centreColumnLabelsMenuItem.getState();
+    alignPanel.paintAlignment(true);
+  }
+
 
 
   /**
@@ -2849,7 +2889,7 @@ public class AlignFrame
   {
     SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
     AlignmentSorter.sortByPID(viewport.getAlignment(),
-                              viewport.getAlignment().getSequenceAt(0));
+                              viewport.getAlignment().getSequenceAt(0), null);
     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
                                     viewport.alignment));
     alignPanel.paintAlignment(true);
@@ -3112,7 +3152,7 @@ public class AlignFrame
       public void actionPerformed(ActionEvent e)
       {
         SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
-        AlignmentSorter.sortByAnnotationScore(scoreLabel, viewport.getAlignment());
+        AlignmentSorter.sortByAnnotationScore(scoreLabel, viewport.getAlignment());//,viewport.getSelectionGroup());
         addHistoryItem(new OrderCommand("Sort by "+scoreLabel, oldOrder, viewport.alignment));
         alignPanel.paintAlignment(true);
       }
@@ -3230,7 +3270,7 @@ public class AlignFrame
    * or just the selected set will be submitted for multiple alignment.
    *
    */
-  private jalview.datamodel.AlignmentView gatherSequencesForAlignment()
+  public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
   {
     // Now, check we have enough sequences
     AlignmentView msa = null;
@@ -3268,12 +3308,14 @@ public class AlignFrame
   }
 
   /**
-   * Decides what is submitted to a secondary structure prediction service,
-   * the currently selected sequence, or the currently selected alignment
+   * Decides what is submitted to a secondary structure prediction service:
+   * the first sequence in the alignment, or in the current selection,
+   * or, if the alignment is 'aligned' (ie padded with gaps), then the
+   * currently selected region or the whole alignment.
    * (where the first sequence in the set is the one that the prediction
    * will be for).
    */
-  AlignmentView gatherSeqOrMsaForSecStrPrediction()
+  public AlignmentView gatherSeqOrMsaForSecStrPrediction()
   {
    AlignmentView seqs = null;
 
@@ -3316,21 +3358,28 @@ public class AlignFrame
     {
       String choice = chooser.getSelectedFile().getPath();
       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
-
+      jalview.io.NewickFile fin = null;
       try
       {
-        jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,
+        fin = new jalview.io.NewickFile(choice,
             "File");
         viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
       }
       catch (Exception ex)
       {
         JOptionPane.showMessageDialog(Desktop.desktop,
-                                      "Problem reading tree file",
                                       ex.getMessage(),
+                                      "Problem reading tree file",
                                       JOptionPane.WARNING_MESSAGE);
         ex.printStackTrace();
       }
+      if (fin!=null && fin.hasWarningMessage())
+      {
+        JOptionPane.showMessageDialog(Desktop.desktop,
+                fin.getWarningMessage(),
+                "Possible problem with tree file",
+                JOptionPane.WARNING_MESSAGE);
+      }
     }
   }
 
@@ -3395,7 +3444,7 @@ public class AlignFrame
     {
       ex.printStackTrace();
     }
-
+    
     return tp;
   }
 
@@ -3406,11 +3455,18 @@ public class AlignFrame
    */
   public void BuildWebServiceMenu()
   {
+    // TODO: add support for context dependent disabling of services based on alignment and current selection
+    // TODO: add additional serviceHandle parameter to specify abstract handler class independently of AbstractName
+    // TODO: add in rediscovery GUI function to restart discoverer
+    // TODO: group services by location as well as function and/or introduce object broker mechanism.
     if ( (Discoverer.services != null)
         && (Discoverer.services.size() > 0))
     {
+      // TODO: refactor to allow list of AbstractName/Handler bindings to be stored or retrieved from elsewhere
       Vector msaws = (Vector) Discoverer.services.get("MsaWS");
       Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");
+      Vector seqsrch = (Vector) Discoverer.services.get("SeqSearch");
+      // TODO: move GUI generation code onto service implementation - so a client instance attaches itself to the GUI with method call like jalview.ws.MsaWSClient.bind(servicehandle, Desktop.instance, alignframe)
       Vector wsmenu = new Vector();
       final AlignFrame af = this;
       if (msaws != null)
@@ -3421,42 +3477,9 @@ public class AlignFrame
         {
           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.
               get(i);
-          final JMenuItem method = new JMenuItem(sh.getName());
-          method.addActionListener(new ActionListener()
-          {
-            public void actionPerformed(ActionEvent e)
-            {
-              AlignmentView msa = gatherSequencesForAlignment();
-              new jalview.ws.MsaWSClient(sh, title, msa,
-                                         false, true,
-                                         viewport.getAlignment().getDataset(),
-                                         af);
-
-            }
-
-          });
-          msawsmenu.add(method);
-          // Deal with services that we know accept partial alignments.
-          if (sh.getName().indexOf("lustal") > -1)
-          {
-            // We know that ClustalWS can accept partial alignments for refinement.
-            final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");
-            methodR.addActionListener(new ActionListener()
-            {
-              public void actionPerformed(ActionEvent e)
-              {
-                AlignmentView msa = gatherSequencesForAlignment();
-                new jalview.ws.MsaWSClient(sh, title, msa,
-                                           true, true,
-                                           viewport.getAlignment().getDataset(),
-                                           af);
-
-              }
-
-            });
-            msawsmenu.add(methodR);
-
-          }
+          jalview.ws.WSClient impl = jalview.ws.Discoverer.getServiceClient(sh);
+          impl.attachWSMenuEntry(msawsmenu, this);
+        
         }
         wsmenu.add(msawsmenu);
       }
@@ -3468,32 +3491,25 @@ public class AlignFrame
         {
           final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
               secstrpr.get(i);
-          final JMenuItem method = new JMenuItem(sh.getName());
-          method.addActionListener(new ActionListener()
-          {
-            public void actionPerformed(ActionEvent e)
-            {
-              AlignmentView msa = gatherSeqOrMsaForSecStrPrediction();
-              if (msa.getSequences().length == 1)
-              {
-                // Single Sequence prediction
-                new jalview.ws.JPredClient(sh, title, false, msa, af, true);
-              }
-              else
-              {
-                if (msa.getSequences().length > 1)
-                {
-                  // Sequence profile based prediction
-                  new jalview.ws.JPredClient(sh,
-                      title, true, msa, af, true);
-                }
-              }
-            }
-          });
-          secstrmenu.add(method);
+          jalview.ws.WSClient impl = jalview.ws.Discoverer.getServiceClient(sh);
+          impl.attachWSMenuEntry(secstrmenu, this);
         }
         wsmenu.add(secstrmenu);
       }
+      if (seqsrch!=null)
+      {
+        // Add any sequence search services
+        final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
+        for (int i = 0, j = seqsrch.size(); i < j; i++)
+        {
+          final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
+              seqsrch.elementAt(i);
+          jalview.ws.WSClient impl = jalview.ws.Discoverer.getServiceClient(sh);
+          impl.attachWSMenuEntry(seqsrchmenu, this);
+        }
+        // finally, add the whole shebang onto the webservices menu
+        wsmenu.add(seqsrchmenu); 
+      }
       resetWebServiceMenu();
       for (int i = 0, j = wsmenu.size(); i < j; i++)
       {
@@ -3505,9 +3521,6 @@ public class AlignFrame
       resetWebServiceMenu();
       this.webService.add(this.webServiceNoServices);
     }
-    // TODO: add in rediscovery function
-    // TODO: reduce code redundancy.
-    // TODO: group services by location as well as function.
   }
 
 
@@ -3527,7 +3540,7 @@ public class AlignFrame
 
       public void actionPerformed(ActionEvent e)
       {
-        new jalview.io.DBRefFetcher(
+        new jalview.ws.DBRefFetcher(
                 alignPanel.av.getSequenceSelection(),
                 alignPanel.alignFrame).fetchDBRefs(false);
       }
@@ -3553,9 +3566,165 @@ public class AlignFrame
       vs.storeJalview( chooser.getSelectedFile().getAbsolutePath(), this);
     }
   }*/
+  /**
+   * prototype of an automatically enabled/disabled analysis function
+   *
+   */
+  protected void setShowProductsEnabled()
+  {
+    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)
+  {
+    boolean showp=false;
+    try {
+      showProducts.removeAll();
+      final boolean dna = viewport.getAlignment().isNucleotide();
+      final Alignment ds = dataset;
+      String[] ptypes = 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]);
+        xtype.addActionListener(new ActionListener() {
+
+          public void actionPerformed(ActionEvent e)
+          {
+            // TODO: new thread for this call with vis-delay
+            af.showProductsFor(sel, ds, isRegSel, dna, source);
+          }
+          
+        });
+        showProducts.add(xtype);
+      }
+      showProducts.setVisible(showp);
+      showProducts.setEnabled(showp);
+    } catch (Exception e)
+    {
+      jalview.bin.Cache.log.warn("canTranslate threw an exception - please report to help@jalview.org",e);
+     return false;
+    }
+    return showp;
+  }
+protected void showProductsFor(SequenceI[] sel, Alignment ds, boolean isRegSel, boolean dna, String source)
+  {
+  final boolean fisRegSel = isRegSel;
+  final boolean fdna = dna;
+  final String fsrc = source;
+  final AlignFrame ths = this;
+  final SequenceI[] fsel = sel;
+  Runnable foo = new Runnable() {
 
+    public void run()
+    {
+      final long sttime = System.currentTimeMillis();
+      ths.setProgressBar("Searching for sequences from "+fsrc, sttime);
+      try {
+        Alignment ds = ths.getViewport().alignment.getDataset(); // update our local dataset reference
+      Alignment prods = CrossRef.findXrefSequences(fsel, fdna, fsrc, ds);
+      if (prods!=null)
+      {
+        SequenceI[] sprods = new SequenceI[prods.getHeight()];
+        for (int s=0; s<sprods.length;s++)
+        {
+          sprods[s] = (prods.getSequenceAt(s)).deriveSequence();
+          if (ds.getSequences()==null || !ds.getSequences().contains(sprods[s].getDatasetSequence()))
+            ds.addSequence(sprods[s].getDatasetSequence());
+          sprods[s].updatePDBIds();
+        }
+        Alignment al = new Alignment(sprods);
+        AlignedCodonFrame[] cf = prods.getCodonFrames();
+        for (int s=0; cf!=null && s<cf.length; s++)
+        {
+          al.addCodonFrame(cf[s]);
+          cf[s] = null;
+        }
+        al.setDataset(ds);
+        AlignFrame naf = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+        String newtitle =""+((fdna) ? "Proteins " : "Nucleotides ") + " for "+((fisRegSel) ? "selected region of " : "")
+                + getTitle();
+        Desktop.addInternalFrame(naf, newtitle, DEFAULT_WIDTH,
+                DEFAULT_HEIGHT);
+      } else {
+        System.err.println("No Sequences generated for xRef type "+fsrc);
+      }
+      }
+      catch (Exception e)
+      {
+        jalview.bin.Cache.log.error("Exception when finding crossreferences",e);
+      }
+      catch (Error e)
+      {
+        jalview.bin.Cache.log.error("Error when finding crossreferences",e);
+      }
+      ths.setProgressBar("Finished searching for sequences from "+fsrc, sttime);
+    }
+    
+  };
+  Thread frunner = new Thread(foo);
+  frunner.start();
+  }
 
 
+public boolean canShowTranslationProducts(SequenceI[] selection, AlignmentI alignment)
+{
+  // old way
+  try {
+      return (jalview.analysis.Dna.canTranslate(selection, viewport.getViewAsVisibleContigs(true)));
+  } catch (Exception e)
+  {
+    jalview.bin.Cache.log.warn("canTranslate threw an exception - please report to help@jalview.org",e);
+   return false;
+  }
+}
+
+public void showProducts_actionPerformed(ActionEvent e)
+{
+  ///////////////////////////////
+  // Collect Data to be translated/transferred
+  
+  SequenceI [] selection = viewport.getSequenceSelection();
+  AlignmentI al  = null;
+  try {
+      al = jalview.analysis.Dna.CdnaTranslate(selection, viewport.getViewAsVisibleContigs(true),
+          viewport.getGapCharacter(), viewport.getAlignment().getDataset());
+    } catch (Exception ex) {
+      al = null;
+      jalview.bin.Cache.log.debug("Exception during translation.",ex);
+    }
+    if (al==null)
+    {
+      JOptionPane.showMessageDialog(Desktop.desktop,
+          "Please select at least three bases in at least one sequence in order to perform a cDNA translation.",
+          "Translation Failed",
+          JOptionPane.WARNING_MESSAGE);
+    } else {
+      AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+      Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),
+                               DEFAULT_WIDTH,
+                               DEFAULT_HEIGHT);
+    }
+  }
+
 public void showTranslation_actionPerformed(ActionEvent e)
 {
   ///////////////////////////////
@@ -3567,7 +3736,7 @@ public void showTranslation_actionPerformed(ActionEvent e)
   try {
     al = jalview.analysis.Dna.CdnaTranslate(selection, seqstring, viewport.getViewAsVisibleContigs(true),
         viewport.getGapCharacter(), viewport.alignment.getAlignmentAnnotation(),
-        viewport.alignment.getWidth());
+        viewport.alignment.getWidth(), viewport.getAlignment().getDataset());
   } catch (Exception ex) {
     al = null;
     jalview.bin.Cache.log.debug("Exception during translation.",ex);
@@ -3587,9 +3756,10 @@ public void showTranslation_actionPerformed(ActionEvent e)
 }
 
 /**
- * DOCUMENT ME!
- *
- * @param String DOCUMENT ME!
+ * Try to load a features file onto the alignment.
+ * @param file contents or path to retrieve file 
+ * @param type access mode of file (see jalview.io.AlignFile)
+ * @return true if features file was parsed corectly.
  */
 public boolean parseFeaturesFile(String file, String type)
 {
@@ -3690,12 +3860,15 @@ public void drop(DropTargetDropEvent evt)
     }
 }
 
-  // This method will attempt to load a "dropped" file first by testing
-  // whether its and Annotation file, then features file. If both are
-  // false then the user may have dropped an alignment file onto this
-  // AlignFrame
+  /**     
+   * Attempt to load a "dropped" file: First by testing
+   * whether it's and Annotation file, then a JNet file, and finally a features file. If all are
+   * false then the user may have dropped an alignment file onto this
+   * AlignFrame.
+   * @param file either a filename or a URL string.
+   */
    public void loadJalviewDataFile(String file)
-  {
+   {
     try
     {
       String protocol = "File";
@@ -3710,34 +3883,37 @@ public void drop(DropTargetDropEvent evt)
 
       if (!isAnnotation)
       {
-        boolean isGroupsFile = parseFeaturesFile(file,protocol);
-        if (!isGroupsFile)
+        // try to see if its a JNet 'concise' style annotation file *before* we try to parse it as a features file
+        String format = new IdentifyFile().Identify(file, protocol);
+        if(format.equalsIgnoreCase("JnetFile"))
         {
-          String format = new IdentifyFile().Identify(file, protocol);
-
-          if(format.equalsIgnoreCase("JnetFile"))
-          {
-            jalview.io.JPredFile predictions = new jalview.io.JPredFile(
-                file, protocol);
-            new JnetAnnotationMaker().add_annotation(predictions,
+          jalview.io.JPredFile predictions = new jalview.io.JPredFile(
+                  file, protocol);
+          new JnetAnnotationMaker().add_annotation(predictions,
                 viewport.getAlignment(),
                 0, false);
-            alignPanel.adjustAnnotationHeight();
-            alignPanel.paintAlignment(true);
-          }
-          else
+          isAnnotation=true;
+        }
+        else
+        {
+          // try to parse it as a features file
+          boolean isGroupsFile = parseFeaturesFile(file,protocol);
+          // if it wasn't a features file then we just treat it as a general alignment file to load into the current view.
+          if (!isGroupsFile)
           {
             new FileLoader().LoadFile(viewport, file, protocol, format);
+          } else {
+            alignPanel.paintAlignment(true);
+          }
         }
       }
-      }
-      else
+      if (isAnnotation)
       {
-        // (isAnnotation)
+        
         alignPanel.adjustAnnotationHeight();
         buildSortByAnnotationScoresMenu();
+        alignPanel.paintAlignment(true);
       }
-
     }
     catch (Exception ex)
     {
@@ -3785,7 +3961,7 @@ public void drop(DropTargetDropEvent evt)
   protected void extractScores_actionPerformed(ActionEvent e)
   {
     ParseProperties pp = new jalview.analysis.ParseProperties(viewport.alignment);
-    if (pp.getScoresFromDescription("col", "score column ", "\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)")>0)
+    if (pp.getScoresFromDescription("col", "score column ", "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)", true)>0)
     {
       buildSortByAnnotationScoresMenu();
     }