JAL-2582 recognise ENS…P peptide IDs and make two getParent requests to get gene ID.
[jalview.git] / src / jalview / ext / ensembl / EnsemblGene.java
index 0cecc59..47b473a 100644 (file)
@@ -1,17 +1,36 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.ext.ensembl;
 
 import jalview.api.FeatureColourI;
-import jalview.api.FeatureSettingsI;
+import jalview.api.FeatureSettingsModelI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.io.gff.SequenceOntologyFactory;
 import jalview.io.gff.SequenceOntologyI;
-import jalview.schemes.FeatureColourAdapter;
+import jalview.schemes.FeatureColour;
 import jalview.schemes.FeatureSettingsAdapter;
 import jalview.util.MapList;
-import jalview.util.StringUtils;
 
 import java.awt.Color;
 import java.io.UnsupportedEncodingException;
@@ -29,9 +48,6 @@ import com.stevesoft.pat.Regex;
  */
 public class EnsemblGene extends EnsemblSeqProxy
 {
-  private static final List<String> CROSS_REFERENCES = Arrays
-          .asList(new String[] { "CCDS" });
-
   private static final String GENE_PREFIX = "gene:";
 
   /*
@@ -104,59 +120,108 @@ public class EnsemblGene extends EnsemblSeqProxy
    * </ul>
    * 
    * @param query
-   *          one or more identifiers separated by a space
-   * @return an alignment containing one or more genes, and possibly
-   *         transcripts, or null
+   *          a single gene or transcript identifier or gene name
+   * @return an alignment containing a gene, and possibly transcripts, or null
    */
   @Override
   public AlignmentI getSequenceRecords(String query) throws Exception
   {
-    // todo: tidy up handling of one or multiple accession ids
-    String[] queries = query.split(getAccessionSeparator());
-
     /*
-     * if given a transcript id, look up its gene parent
+     * convert to a non-duplicated list of gene identifiers
      */
-    if (isTranscriptIdentifier(query))
+    List<String> geneIds = getGeneIds(query);
+
+    AlignmentI al = null;
+    for (String geneId : geneIds)
     {
-      // we are assuming all transcripts have the same gene parent here
-      query = new EnsemblLookup(getDomain()).getParent(queries[0]);
-      if (query == null)
+      /*
+       * fetch the gene sequence(s) with features and xrefs
+       */
+      AlignmentI geneAlignment = super.getSequenceRecords(geneId);
+      if (geneAlignment == null)
       {
-        return null;
+        continue;
+      }
+      if (geneAlignment.getHeight() == 1)
+      {
+        getTranscripts(geneAlignment, geneId);
+      }
+      if (al == null)
+      {
+        al = geneAlignment;
+      }
+      else
+      {
+        al.append(geneAlignment);
       }
     }
+    return al;
+  }
 
-    /*
-     * if given a gene or other external name, lookup and fetch 
-     * the corresponding gene for all model organisms 
-     */
-    if (!isGeneIdentifier(query))
+  /**
+   * Converts a query, which may contain one or more gene or transcript
+   * identifiers, into a non-redundant list of gene identifiers.
+   * 
+   * @param accessions
+   * @return
+   */
+  List<String> getGeneIds(String accessions)
+  {
+    List<String> geneIds = new ArrayList<String>();
+
+    for (String acc : accessions.split(getAccessionSeparator()))
     {
-      List<String> geneIds = new EnsemblSymbol(getDomain()).getIds(query);
-      if (geneIds.isEmpty())
+      if (isGeneIdentifier(acc))
       {
-        return null;
+        if (!geneIds.contains(acc))
+        {
+          geneIds.add(acc);
+        }
       }
-      String theIds = StringUtils.listToDelimitedString(geneIds,
-              getAccessionSeparator());
-      return getSequenceRecords(theIds);
-    }
 
-    /*
-     * fetch the gene sequence(s) with features and xrefs
-     */
-    AlignmentI al = super.getSequenceRecords(query);
+      /*
+       * if given a transcript id, look up its gene parent
+       */
+      else if (isTranscriptIdentifier(acc))
+      {
+        String geneId = new EnsemblLookup(getDomain()).getParent(acc);
+        if (geneId != null && !geneIds.contains(geneId))
+        {
+          geneIds.add(geneId);
+        }
+      }
+      else if (isProteinIdentifier(acc))
+      {
+        String tscriptId = new EnsemblLookup(getDomain()).getParent(acc);
+        if (tscriptId != null)
+        {
+          String geneId = new EnsemblLookup(getDomain())
+                  .getParent(tscriptId);
 
-    /*
-     * if we retrieved a single gene, get its transcripts as well
-     */
-    if (al.getHeight() == 1)
-    {
-      getTranscripts(al, query);
+          if (geneId != null && !geneIds.contains(geneId))
+          {
+            geneIds.add(geneId);
+          }
+        }
+      }
+      /*
+       * if given a gene or other external name, lookup and fetch 
+       * the corresponding gene for all model organisms 
+       */
+      else
+      {
+        List<String> ids = new EnsemblSymbol(getDomain(), getDbSource(),
+                getDbVersion()).getIds(acc);
+        for (String geneId : ids)
+        {
+          if (!geneIds.contains(geneId))
+          {
+            geneIds.add(geneId);
+          }
+        }
+      }
     }
-
-    return al;
+    return geneIds;
   }
 
   /**
@@ -168,7 +233,8 @@ public class EnsemblGene extends EnsemblSeqProxy
    */
   protected String getGeneIdentifiersForName(String query)
   {
-    List<String> ids = new EnsemblSymbol(getDomain()).getIds(query);
+    List<String> ids = new EnsemblSymbol(getDomain(), getDbSource(),
+            getDbVersion()).getIds(query);
     if (ids != null)
     {
       for (String id : ids)
@@ -229,8 +295,7 @@ public class EnsemblGene extends EnsemblSeqProxy
         }
       }
       gene.setSequenceFeatures(filtered
-              .toArray(new SequenceFeature[filtered
-              .size()]));
+              .toArray(new SequenceFeature[filtered.size()]));
     }
   }
 
@@ -465,15 +530,6 @@ public class EnsemblGene extends EnsemblSeqProxy
     return false;
   }
 
-  @Override
-  protected List<String> getCrossReferenceDatabases()
-  {
-    // found these for ENSG00000157764 on 30/01/2016:
-    // return new String[] {"Vega_gene", "OTTG", "ENS_LRG_gene", "ArrayExpress",
-    // "EntrezGene", "HGNC", "MIM_GENE", "MIM_MORBID", "WikiGene"};
-    return CROSS_REFERENCES;
-  }
-
   /**
    * Override to do nothing as Ensembl doesn't return a protein sequence for a
    * gene identifier
@@ -489,12 +545,23 @@ public class EnsemblGene extends EnsemblSeqProxy
     return ACCESSION_REGEX;
   }
 
+  /**
+   * Returns a descriptor for suitable feature display settings with
+   * <ul>
+   * <li>only exon or sequence_variant features (or their subtypes in the
+   * Sequence Ontology) visible</li>
+   * <li>variant features coloured red</li>
+   * <li>exon features coloured by label (exon name)</li>
+   * <li>variants displayed above (on top of) exons</li>
+   * </ul>
+   */
   @Override
-  public FeatureSettingsI getFeatureColourScheme()
+  public FeatureSettingsModelI getFeatureColourScheme()
   {
     return new FeatureSettingsAdapter()
     {
       SequenceOntologyI so = SequenceOntologyFactory.getInstance();
+
       @Override
       public boolean isFeatureDisplayed(String type)
       {
@@ -507,7 +574,7 @@ public class EnsemblGene extends EnsemblSeqProxy
       {
         if (so.isA(type, SequenceOntologyI.EXON))
         {
-          return new FeatureColourAdapter()
+          return new FeatureColour()
           {
             @Override
             public boolean isColourByLabel()
@@ -518,7 +585,7 @@ public class EnsemblGene extends EnsemblSeqProxy
         }
         if (so.isA(type, SequenceOntologyI.SEQUENCE_VARIANT))
         {
-          return new FeatureColourAdapter()
+          return new FeatureColour()
           {
 
             @Override