X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fext%2Fensembl%2FEnsemblGene.java;h=36b19e25375aaa31ed24ae1cf694e0906ab0fd11;hb=a4f2a7f356b8edab17a9a5bb6f2e71a1419792a9;hp=115ecd43de4a7cb977fb49674be0e5406d9a91c7;hpb=f4766a7bbcfae845fc95923b01fa14ff83d589ff;p=jalview.git diff --git a/src/jalview/ext/ensembl/EnsemblGene.java b/src/jalview/ext/ensembl/EnsemblGene.java index 115ecd4..36b19e2 100644 --- a/src/jalview/ext/ensembl/EnsemblGene.java +++ b/src/jalview/ext/ensembl/EnsemblGene.java @@ -100,6 +100,12 @@ public class EnsemblGene extends EnsemblSeqProxy return EnsemblSeqType.GENOMIC; } + @Override + protected String getObjectType() + { + return OBJECT_TYPE_GENE; + } + /** * Returns an alignment containing the gene(s) for the given gene or * transcript identifier, or external identifier (e.g. Uniprot id). If given a @@ -147,10 +153,13 @@ public class EnsemblGene extends EnsemblSeqProxy continue; } - parseChromosomeLocations(geneAlignment); - if (geneAlignment.getHeight() == 1) { + // ensure id has 'correct' case for the Ensembl identifier + geneId = geneAlignment.getSequenceAt(0).getName(); + + findGeneLoci(geneAlignment.getSequenceAt(0), geneId); + getTranscripts(geneAlignment, geneId); } if (al == null) @@ -166,105 +175,104 @@ public class EnsemblGene extends EnsemblSeqProxy } /** + * Calls the /lookup/id REST service, parses the response for gene + * coordinates, and if successful, adds these to the sequence. If this fails, + * fall back on trying to parse the sequence description in case it is in + * Ensembl-gene format e.g. chromosome:GRCh38:17:45051610:45109016:1. + * + * @param seq + * @param geneId + */ + void findGeneLoci(SequenceI seq, String geneId) + { + GeneLociI geneLoci = new EnsemblLookup(getDomain()).getGeneLoci(geneId); + if (geneLoci != null) + { + seq.setGeneLoci(geneLoci.getSpeciesId(), geneLoci.getAssemblyId(), + geneLoci.getChromosomeId(), geneLoci.getMap()); + } + else + { + parseChromosomeLocations(seq); + } + } + + /** * Parses and saves fields of an Ensembl-style description e.g. * chromosome:GRCh38:17:45051610:45109016:1 * - * @param alignment + * @param seq */ - private void parseChromosomeLocations(AlignmentI alignment) + boolean parseChromosomeLocations(SequenceI seq) { - for (SequenceI seq : alignment.getSequences()) + String description = seq.getDescription(); + if (description == null) { - String description = seq.getDescription(); - if (description == null) + return false; + } + String[] tokens = description.split(":"); + if (tokens.length == 6 && tokens[0].startsWith(DBRefEntry.CHROMOSOME)) + { + String ref = tokens[1]; + String chrom = tokens[2]; + try { - continue; - } - String[] tokens = description.split(":"); - if (tokens.length == 6 && tokens[0].startsWith(DBRefEntry.CHROMOSOME)) + int chStart = Integer.parseInt(tokens[3]); + int chEnd = Integer.parseInt(tokens[4]); + boolean forwardStrand = "1".equals(tokens[5]); + String species = ""; // not known here + int[] from = new int[] { seq.getStart(), seq.getEnd() }; + int[] to = new int[] { forwardStrand ? chStart : chEnd, + forwardStrand ? chEnd : chStart }; + MapList map = new MapList(from, to, 1, 1); + seq.setGeneLoci(species, ref, chrom, map); + return true; + } catch (NumberFormatException e) { - String ref = tokens[1]; - String chrom = tokens[2]; - try - { - int chStart = Integer.parseInt(tokens[3]); - int chEnd = Integer.parseInt(tokens[4]); - boolean forwardStrand = "1".equals(tokens[5]); - String species = ""; // dunno yet! - int[] from = new int[] { seq.getStart(), seq.getEnd() }; - int[] to = new int[] { forwardStrand ? chStart : chEnd, - forwardStrand ? chEnd : chStart }; - MapList map = new MapList(from, to, 1, 1); - seq.setGeneLoci(species, ref, chrom, map); - } catch (NumberFormatException e) - { - System.err.println("Bad integers in description " + description); - } + System.err.println("Bad integers in description " + description); } } + return false; } /** - * Converts a query, which may contain one or more gene or transcript - * identifiers, into a non-redundant list of gene identifiers. + * Converts a query, which may contain one or more gene, transcript, or + * external (to Ensembl) identifiers, into a non-redundant list of gene + * identifiers. * * @param accessions * @return */ List getGeneIds(String accessions) { - List geneIds = new ArrayList(); + List geneIds = new ArrayList<>(); for (String acc : accessions.split(getAccessionSeparator())) { - if (isGeneIdentifier(acc)) - { - if (!geneIds.contains(acc)) - { - geneIds.add(acc); - } - } - /* - * if given a transcript id, look up its gene parent + * First try lookup as an Ensembl (gene or transcript) identifier */ - else if (isTranscriptIdentifier(acc)) + String geneId = new EnsemblLookup(getDomain()).getGeneId(acc); + if (geneId != null) { - String geneId = new EnsemblLookup(getDomain()).getParent(acc); - if (geneId != null && !geneIds.contains(geneId)) + if (!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 (geneId != null && !geneIds.contains(geneId)) - { - geneIds.add(geneId); - } - } - // NOTE - acc is lost if it resembles an ENS.+ ID but isn't actually - // resolving to one... e.g. ENSMICP00000009241 - } - /* - * if given a gene or other external name, lookup and fetch - * the corresponding gene for all model organisms - */ else { + /* + * if given a gene or other external name, lookup and fetch + * the corresponding gene for all model organisms + */ List ids = new EnsemblSymbol(getDomain(), getDbSource(), - getDbVersion()).getIds(acc); - for (String geneId : ids) + getDbVersion()).getGeneIds(acc); + for (String id : ids) { - if (!geneIds.contains(geneId)) + if (!geneIds.contains(id)) { - geneIds.add(geneId); + geneIds.add(id); } } } @@ -273,30 +281,6 @@ public class EnsemblGene extends EnsemblSeqProxy } /** - * Attempts to get Ensembl stable identifiers for model organisms for a gene - * name by calling the xrefs symbol REST service to resolve the gene name. - * - * @param query - * @return - */ - protected String getGeneIdentifiersForName(String query) - { - List ids = new EnsemblSymbol(getDomain(), getDbSource(), - getDbVersion()).getIds(query); - if (ids != null) - { - for (String id : ids) - { - if (isGeneIdentifier(id)) - { - return id; - } - } - } - return null; - } - - /** * Constructs all transcripts for the gene, as identified by "transcript" * features whose Parent is the requested gene. The coding transcript * sequences (i.e. with introns omitted) are added to the alignment. @@ -396,7 +380,7 @@ public class EnsemblGene extends EnsemblSeqProxy int transcriptLength = 0; final char[] geneChars = gene.getSequence(); int offset = gene.getStart(); // to convert to 0-based positions - List mappedFrom = new ArrayList(); + List mappedFrom = new ArrayList<>(); for (SequenceFeature sf : splices) { @@ -438,7 +422,7 @@ public class EnsemblGene extends EnsemblSeqProxy * transfer features to the new sequence; we use EnsemblCdna to do this, * to filter out unwanted features types (see method retainFeature) */ - List mapTo = new ArrayList(); + List mapTo = new ArrayList<>(); mapTo.add(new int[] { 1, transcriptLength }); MapList mapping = new MapList(mappedFrom, mapTo, 1, 1); EnsemblCdna cdna = new EnsemblCdna(getDomain()); @@ -524,7 +508,7 @@ public class EnsemblGene extends EnsemblSeqProxy protected List getTranscriptFeatures(String accId, SequenceI geneSequence) { - List transcriptFeatures = new ArrayList(); + List transcriptFeatures = new ArrayList<>(); String parentIdentifier = GENE_PREFIX + accId; @@ -536,7 +520,7 @@ public class EnsemblGene extends EnsemblSeqProxy for (SequenceFeature sf : sfs) { String parent = (String) sf.getValue(PARENT); - if (parentIdentifier.equals(parent)) + if (parentIdentifier.equalsIgnoreCase(parent)) { transcriptFeatures.add(sf); } @@ -564,22 +548,27 @@ public class EnsemblGene extends EnsemblSeqProxy } /** - * Answers true for a feature of type 'gene' (or a sub-type of gene in the - * Sequence Ontology), whose ID is the accession we are retrieving + * Answers a list of sequence features (if any) whose type is 'gene' (or a + * subtype of gene in the Sequence Ontology), and whose ID is the accession we + * are retrieving */ @Override - protected boolean identifiesSequence(SequenceFeature sf, String accId) + protected List getIdentifyingFeatures(SequenceI seq, + String accId) { - if (SequenceOntologyFactory.getInstance().isA(sf.getType(), - SequenceOntologyI.GENE)) + List result = new ArrayList<>(); + List sfs = seq.getFeatures() + .getFeaturesByOntology(SequenceOntologyI.GENE); + for (SequenceFeature sf : sfs) { - String id = (String) sf.getValue(ID); - if ((GENE_PREFIX + accId).equals(id)) + // NB features as gff use 'ID'; rest services return as 'id' + String id = (String) sf.getValue("ID"); + if ((GENE_PREFIX + accId).equalsIgnoreCase(id)) { - return true; + result.add(sf); } } - return false; + return result; } /** @@ -601,7 +590,7 @@ public class EnsemblGene extends EnsemblSeqProxy if (isTranscript(type)) { String parent = (String) sf.getValue(PARENT); - if (!(GENE_PREFIX + accessionId).equals(parent)) + if (!(GENE_PREFIX + accessionId).equalsIgnoreCase(parent)) { return false; } @@ -610,17 +599,6 @@ public class EnsemblGene extends EnsemblSeqProxy } /** - * Answers false. This allows an optimisation - a single 'gene' feature is all - * that is needed to identify the positions of the gene on the genomic - * sequence. - */ - @Override - protected boolean isSpliceable() - { - return false; - } - - /** * Override to do nothing as Ensembl doesn't return a protein sequence for a * gene identifier */