Question: I'm trying to get taxonomic lineage from UniProt with the following SPARQL query (based on [this](https://www.biostars.org/p/159265/#159295) and [this](https://www.biostars.org/p/57569/#57583) answers):

prefix rdfs:
prefix taxon:
prefix :

select ?ancestor ?name ?rank ?part_of_lineage
where {

taxon:9597 rdfs:subClassOf ?ancestor .

?ancestor :scientificName ?name ;
:partOfLineage ?part_of_lineage ;
:rank ?rank .

} order by ?rank

This query yields 14 entries:

ancestor name rank part_of_lineage

taxon:40674 Mammalia :Class true
taxon:9604 Hominidae :Family true
taxon:9596 Pan :Genus true
taxon:314293 Simiiformes :Infraorder false
taxon:33208 Metazoa :Kingdom true
taxon:9443 Primates :Order true
taxon:9526 Catarrhini :Parvorder true
taxon:7711 Chordata :Phylum true
taxon:207598 Homininae :Subfamily false
taxon:376913 Haplorrhini :Suborder true
taxon:89593 Craniata :Subphylum true
taxon:314295 Hominoidea :Superfamily false
taxon:2759 Eukaryota :Superkingdom true
taxon:314146 Euarchontoglires :Superorder true

You can try it with [YASGUI](http://yasgui.org/short/Sy6sUPWZl).

### Questions

1. Note, that unlike in the referred answer, I used `rdfs:subClassOf` without `+`, because if I use `rdfs:subClassOf+`, I get this error message from UniProt:

> Exception:virtuoso.jdbc4.VirtuosoException: TN...: Exceeded 1000000000 bytes in transitive temp memory. use t_distinct, t_max or more T_MAX_memory options to limit the search or increase the pool

Is it a bug in their storage backend or I'm misusing `rdfs:subClassOf+`?

2. As far as I understand, the `rdfs:subClassOf` relationship is _semantically_ transitive, but it should connect only directly related entities. So if you want to get direct ancestor, you can use it one, if you want to get all ancestors, you can use "property paths" feature with `rdfs:subClassOf+`.

But as far as I see from the results above and this query:

describe
from

each node in the UniProt taxonomy graph is a subclass of many other nodes.
Why is it so and how can I get just the direct parent of a given taxon in this situation?

3. Having many ancestors, is there a way to order them (using SPARQL, without postprocessing results) _by taxonomic rank_ (not lexicographically as in the above query)? This would solve the previous question.

4. If you open [_Pan paniscus_ `9597`](http://purl.uniprot.org/taxonomy/9597) from the example above on UniProt, you will see that its lineage is much longer, but some nodes in it are grey. How is this lineage on the UniProt website is related to the results of the query?

5. If you check the [NCBI Taxonomy](https://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?lvl=0&id=9597), the _abbreviated_ lineage is also 14 nodes:

Eukaryota; Metazoa; Chordata; Craniata; Vertebrata; Euteleostomi; Mammalia; Eutheria; Euarchontoglires; Primates; Haplorrhini; Catarrhini; Hominidae; Pan

But not all of them coincide! So what do I get in those results? Some random subset of the lineage?

6. Finally, what does the `:partOfLineage` property mean? [Documentation](http://www.uniprot.org/core/#http://purl.uniprot.org/core/partOfLineage) says:

> True for taxa that can appear as part of an organism's lineage

But I don't understand what it means. Aren't all nodes parts of some lineage?

P.S. I read UniProt [Taxonomy](http://www.uniprot.org/help/taxonomy) and [Taxonomic lineage](http://www.uniprot.org/help/taxonomic_lineage) documentation. But it doesn't answer on my questions.

**UPDATE** Regarding my claim in the question 5.

Here is the lineage from UniProt ([9597](http://www.uniprot.org/taxonomy/9597)):

- ✔︎ **Eukaryota**
- ✘ Opisthokonta
- ✔︎ **Metazoa**
- ✘ Eumetazoa
- ✘ Bilateria
- ✘ Deuterostomia
- ✔︎ **Chordata**
- ✔︎ **Craniata**
- ✘ **Vertebrata**
- ✘ Gnathostomata
- ✘ Teleostomi
- ✘ **Euteleostomi**
- ✘ Sarcopterygii
- ✘ Dipnotetrapodomorpha
- ✘ Tetrapoda
- ✘ Amniota
- ✔︎ **Mammalia**
- ✘ Theria
- ✘ **Eutheria**
- ✘ Boreoeutheria
- ✔︎ **Euarchontoglires**
- ✔︎ **Primates**
- ✔︎ **Haplorrhini**
- ✔︎ Simiiformes
- ✔︎ **Catarrhini**
- ✔︎ Hominoidea
- ✔︎ **Hominidae**
- ✔︎ Homininae
- ✔︎ **Pan**

Those in bold are the ones with `:partOfLineage true`. The checkmarks/crosses on the left mean that this taxon is present/absent in the query result. Note, that it contains both types of nodes (not only from the abbreviated linage).

Answer: This a very good set of questions, and as lead developer for the sparql.uniprot.org endpoint I will try to answer them all.
However, in the future, do try to ask at help@uniprot.org in the future, we do not always check Biostars!

1. Transitive queries are problematic in all the SPARQL back-ends that are build upon relational style engines. Virtuoso, on sparql.uniprot.org sometimes works with rdfs:subClassOf, sometimes not depending on exact queries. Which is why we materialize this relation for rdfs:subClassOf. Which is why '+' is no longer needed. Although, I think I made an error in this materialization (I might miss one step at the top). I need to look into this.

2. You can use the inverse relation from the skos side

PREFIX taxon:<http://purl.uniprot.org/taxonomy/>
PREFIX skos:<http://www.w3.org/2004/02/skos/core#>
PREFIX up:<http://purl.uniprot.org/core/>
SELECT ?direct_child_of_bacteria
{
taxon:2 rdf:type up:Taxon ;
skos:narrowerTransitive ?direct_child_of_bacteria .
}

3. No as we do not put that rank relation in our RDF files so no way to extract that.
4. This is directly related to number 6. `:partOfLineage` means a node that Swiss-Prot curators consider informative enough to want to see in the Swiss-Prot flatfile serialization and is only present in the RDF so that we can roundtrip between these two formats.
5. The difference is that not every taxon node in the NCBI has a rank. You can see that in this query. This is why you are seeing less results in the sparql result view than on the taxon record pages.

prefix rdfs:
prefix taxon:
prefix :

select ?ancestor ?name ?rank ?part_of_lineage
where {

taxon:9597 rdfs:subClassOf ?ancestor .

?ancestor :scientificName ?name ;
:partOfLineage ?part_of_lineage .
OPTIONAL {
?ancestor :rank ?rank .
}
}