{ "cells": [ { "cell_type": "markdown", "id": "beb3c9fb", "metadata": {}, "source": [ "# OAK Developers Tutorial\n", "\n", "This tutorial is primarily for **Python Developers** who wish to use OAK in their applications. These include\n", "applications such as:\n", "\n", "- building ontology-driven data portals\n", "- creating curation tools\n", "- data science and machine learning applications\n", "- web services\n", "\n", "Some basic knowledge of the overall architecture and capabilities of OAK is assumed.\n", "\n", "You may want to start with the slides on the command line here: https://doi.org/10.5281/zenodo.7708963\n", "\n", "Or part 1 of the tutorial here: https://incatools.github.io/ontology-access-kit/intro/tutorial01.html\n", "\n", "There is a video of the walkthrough of this tutorial: https://www.youtube.com/watch?v=nVTWazO_Gu0\n", "\n", "\n", "## How to follow this tutorial\n", "\n", "The easiest way to run this tutorial is to clone the repo and run locally:\n", "\n", "1. clone the repo here https://github.com/INCATools/ontology-access-kit/\n", "2. cd ontology-access-kit\n", "3. poetry install\n", "4. poetry run jupyter notebook\n", "\n", "Alternatively, everything here should work on a fresh install of oak from pypi. You will need to make sure the test files from [tests/input](https://github.com/INCATools/ontology-access-kit/tree/main/tests/input) are accessible.\n", "\n", "Some of the examples work with these test files - others will work with versions of ontologies on the web." ] }, { "cell_type": "markdown", "id": "4c66dd5c", "metadata": {}, "source": [ "### Change directory so that test files are directly accessible\n", "\n", "Note: this is necessary if you are running from a checkout of the OAK repo, since this notebook is in a subfolder" ] }, { "cell_type": "code", "execution_count": 1, "id": "45adb248", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/Users/cjm/repos/ontology-access-kit\n" ] } ], "source": [ "%cd .." ] }, { "cell_type": "markdown", "id": "aad26aed", "metadata": {}, "source": [ "The OAK documentation makes heavy use of some of the unit test files in the [tests/input](https://github.com/INCATools/ontology-access-kit/tree/main/tests/input) folder.\n", "\n", "This include a little mini test subset of GO, available in different formats for the purposes of testing different adapters:" ] }, { "cell_type": "code", "execution_count": 2, "id": "e2438fb1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tests/input/go-nucleus.cx tests/input/go-nucleus.ofn\r\n", "tests/input/go-nucleus.db tests/input/go-nucleus.owl\r\n", "tests/input/go-nucleus.json tests/input/go-nucleus.owl.ttl\r\n", "tests/input/go-nucleus.obo\r\n" ] } ], "source": [ "!ls tests/input/go-nucleus.*" ] }, { "cell_type": "markdown", "id": "8c0c62a0", "metadata": {}, "source": [ "If you are an OAK core developer it helps to be aware of these files, as you will likely be writing new unit tests.\n", "\n", "If one the other hand you just want to use OAK in your own code you don't need to know anything about these except that they are handy for quick testing." ] }, { "cell_type": "markdown", "id": "dae5de64", "metadata": {}, "source": [ "## Running Examples from the OAK sphinx docs\n", "\n", "The sphinx docs include code examples, these are visible from the `>>>`s\n", "\n", "For example, in:\n", "\n", "https://incatools.github.io/ontology-access-kit/packages/interfaces/basic\n", "\n", "You can see sections like this:\n", "\n", "\n", "\n", "If you click the \"copy\" button it will copy the code only (no `>>>`s, and no output) such that you\n", "can paste directly into a Python REPL or a notebook (provided the paths are preserved).\n", "\n", "E.g. try copying this section from the docs\n", "\n", "```python\n", ">>> from oaklib import get_adapter\n", ">>> adapter = get_adapter('tests/input/go-nucleus.db')\n", ">>> print(adapter.label(\"GO:0005634\"))\n", "```" ] }, { "cell_type": "code", "execution_count": 4, "id": "2ec55470", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "nucleus\n" ] } ], "source": [ "from oaklib import get_adapter\n", "adapter = get_adapter('tests/input/go-nucleus.db')\n", "print(adapter.label(\"GO:0005634\"))" ] }, { "cell_type": "markdown", "id": "1fa26abb", "metadata": {}, "source": [ "Hurray! All examples throughout the OAK docs should work" ] }, { "cell_type": "markdown", "id": "1733bae5", "metadata": {}, "source": [ "Note that you can play with using different input formats - this should give the same results:" ] }, { "cell_type": "code", "execution_count": 6, "id": "34e9a5a1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "nucleus\n" ] } ], "source": [ "from oaklib import get_adapter\n", "adapter = get_adapter('tests/input/go-nucleus.obo')\n", "print(adapter.label(\"GO:0005634\"))" ] }, { "cell_type": "markdown", "id": "b85e1771", "metadata": {}, "source": [ "## Working with whole ontologies\n", "\n", "Almost all the examples in this tutorial make use of pre-made sqlite versions of ontologies.\n", "\n", "These are specified using [selector](https://incatools.github.io/ontology-access-kit/packages/selectors.html) syntax:\n", "\n", "```\n", "sqlite:obo:ONTID\n", "```\n", "\n", "E.g.\n", "\n", "```\n", "sqlite:obo:cl\n", "```\n", "\n", "When you use this for the first time it will download and cache the file (using pystow), so there may be an initial lag" ] }, { "cell_type": "code", "execution_count": 8, "id": "1f324799", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "neuron\n" ] } ], "source": [ "from oaklib import get_adapter\n", "adapter = get_adapter(\"sqlite:obo:cl\")\n", "print(adapter.label(\"CL:0000540\"))" ] }, { "cell_type": "markdown", "id": "a53f8987", "metadata": {}, "source": [ "Hurray! We successfully fetched the label (name) for a class ID in the cell ontology!\n", "\n", "Note that the `label` method is part of the BasicOntologyInterface" ] }, { "cell_type": "markdown", "id": "bd705733", "metadata": {}, "source": [ "### BasicOntologyInterface\n", "\n", "The [BasicOntologyInterface](https://incatools.github.io/ontology-access-kit/packages/interfaces/basic) provides basic methods that encompass the majority of what most people need to do when\n", "working with ontologies - lookups of various kinds as well as simple graph operations.\n", "\n", "OAK has the architectural concept of separating interfaces from implementations. It helps to read about this concept, but for now you don't need to worry about it. We are using the sql adapter which fully *implements* almost all the existing OAK interfaces" ] }, { "cell_type": "markdown", "id": "e84e5425", "metadata": {}, "source": [ "### Fetching ancestors\n", "\n", "Next we are going to fetch ancestors. \n", "\n", "Note: it would help to review [tutorial part 1](https://incatools.github.io/ontology-access-kit/intro/tutorial01.html) to understand basic concepts of edges, ancestors, and predicates." ] }, { "cell_type": "code", "execution_count": 9, "id": "67273969", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CL:0000540 neuron\n", "BFO:0000002 continuant\n", "BFO:0000004 independent continuant\n", "BFO:0000040 material entity\n", "CL:0000000 cell\n", "CL:0000003 native cell\n", "CL:0000211 electrically active cell\n", "CL:0000255 eukaryotic cell\n", "CL:0000393 electrically responsive cell\n", "CL:0000404 electrically signaling cell\n", "CL:0000540 neuron\n", "CL:0000548 animal cell\n", "CL:0002319 neural cell\n", "CL:0002371 somatic cell\n" ] } ], "source": [ "from oaklib.datamodels.vocabulary import IS_A\n", "for anc in adapter.ancestors(\"CL:0000540\", predicates=[IS_A]):\n", " print(anc, adapter.label(anc))" ] }, { "cell_type": "markdown", "id": "91474cd7", "metadata": {}, "source": [ "### Fetching descendants\n", "\n", "Let's try working with descendants.\n", "\n", "This time we are going to demonstrate how OAK deals with collections.\n", "\n", "__note__ _we expect the following code **not** to work_" ] }, { "cell_type": "code", "execution_count": 10, "id": "954b22b5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PROBLEM: object of type 'generator' has no len()\n" ] } ], "source": [ "neurons = adapter.descendants(\"CL:0000540\", predicates=[IS_A])\n", "try:\n", " print(len(neurons))\n", "except(Exception) as e:\n", " print(f\"PROBLEM: {e}\")" ] }, { "cell_type": "markdown", "id": "265d0cd9", "metadata": {}, "source": [ "Why didn't this work? What does `object of type 'generator' has no len()` mean?\n", "\n", "To understand why we will mention a key concept in OAK, that of the iterator" ] }, { "cell_type": "markdown", "id": "ae574c65", "metadata": {}, "source": [ "### Iterators\n", "\n", "OAK methods rarely return lists - instead they return iterators. This means that code is better adaptable to use cases\n", "where you want to work with potentially very large lists or you want to *stream* results. See:\n", "\n", "See [best practice](https://incatools.github.io/ontology-access-kit/packages/best-practice.html#iterators)\n", "\n", "However, if you don't care about this you can simple use `list(...)` to get a list:" ] }, { "cell_type": "code", "execution_count": 11, "id": "4239552a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "454\n" ] } ], "source": [ "neurons = list(adapter.descendants(\"CL:0000540\", predicates=[IS_A]))\n", "print(len(neurons))" ] }, { "cell_type": "markdown", "id": "818c83f9", "metadata": {}, "source": [ "You can also cast to `set()` to use set operations like intersections.\n", "\n", "For example, let's say we want to compose our neuron query above with a query to fetch all things in the forebrain,\n", "to get all neurons in the forebrain:" ] }, { "cell_type": "code", "execution_count": 12, "id": "695eef7c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "219\n" ] } ], "source": [ "from oaklib.datamodels.vocabulary import IS_A, PART_OF\n", "parts_of_forebrain = set(adapter.descendants(\"UBERON:0001890\", predicates=[IS_A, PART_OF]))\n", "print(len(parts_of_forebrain))" ] }, { "cell_type": "markdown", "id": "942af1e8", "metadata": {}, "source": [ "You may be wondering what Uberon terms are doing here given that we requested the cell ontology in `get_adapter`\n", "\n", "One under-appreciated fact of OBO is that many ontologies are in fact mini \"knowledge graphs\", linking out to nodes in other ontologies. See \n", "\n", " - [extracting using robot](https://oboacademy.github.io/obook/tutorial/robot-tutorial-1/) (OBO Academy)\n", " - [owl format variants](https://oboacademy.github.io/obook/explanation/owl-format-variants/) (OBO Academy)\n", " - [OAK basics](https://incatools.github.io/ontology-access-kit/guide/basics.html) (OAK Guide)\n", " \n", " \n", " OK next lets do an **intersection** between the two lists" ] }, { "cell_type": "code", "execution_count": 13, "id": "96a1a814", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CL:1001435 periglomerular cell\n", "CL:4023040 L2/3-6 intratelencephalic projecting glutamatergic cortical neuron\n", "CL:1001571 hippocampal pyramidal neuron\n", "CL:1001502 mitral cell\n", "CL:1001434 olfactory bulb interneuron\n", "CL:4023048 L4/5 intratelencephalic projecting glutamatergic neuron of the primary motor cortex\n", "CL:1001505 parvocellular neurosecretory cell\n", "CL:4023008 intratelencephalic-projecting glutamatergic cortical neuron\n", "CL:4023049 L5 intratelencephalic projecting glutamatergic neuron of the primary motor cortex\n", "CL:4023047 L2/3 intratelencephalic projecting glutamatergic neuron of the primary motor cortex\n", "CL:4023081 inverted L6 intratelencephalic projecting glutamatergic neuron of the primary motor cortex (Mmus)\n", "CL:4023050 L6 intratelencephalic projecting glutamatergic neuron of the primary motor cortex\n", "CL:1001503 olfactory bulb tufted cell\n", "CL:4023080 stellate L6 intratelencephalic projecting glutamatergic neuron of the primary motor cortex (Mmus)\n" ] } ], "source": [ "for cell in parts_of_forebrain.intersection(neurons):\n", " print(cell, adapter.label(cell))" ] }, { "cell_type": "markdown", "id": "562170d3", "metadata": {}, "source": [ "This is **all the neurons that are part of the forebrain**.\n", "\n", "Readers familiar with OWL and Protege may like to think of this as similar to a DL query for the expression `neuron and part-of some forebrain` -- there are some theoretical differences we won't get into here but for practical purposes the results should be the same." ] }, { "cell_type": "markdown", "id": "615f4deb", "metadata": {}, "source": [ "### Relationships\n", "\n", "The above example uses the ancestors and descendants query in [BasicOntologyInterface](https://incatools.github.io/ontology-access-kit/packages/interfaces/basic).\n", "\n", "We can also get the relationships using the `relationships` method:" ] }, { "cell_type": "code", "execution_count": 15, "id": "b61c3832", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('CL:0000540', 'RO:0002215', 'GO:0019226')\n", "('CL:0000540', 'rdfs:subClassOf', 'BFO:0000040')\n", "('CL:0000540', 'rdfs:subClassOf', 'CL:0000393')\n", "('CL:0000540', 'rdfs:subClassOf', 'CL:0000404')\n", "('CL:0000540', 'rdfs:subClassOf', 'CL:0002319')\n" ] } ], "source": [ "for rel in adapter.relationships([\"CL:0000540\"]):\n", " print(rel)" ] }, { "cell_type": "code", "execution_count": 17, "id": "eb1e98a2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " RO:0002215 capable of GO:0019226 transmission of nerve impulse\n", " rdfs:subClassOf None BFO:0000040 material entity\n", " rdfs:subClassOf None CL:0000393 electrically responsive cell\n", " rdfs:subClassOf None CL:0000404 electrically signaling cell\n", " rdfs:subClassOf None CL:0002319 neural cell\n" ] } ], "source": [ "for _s, p, o in adapter.relationships([\"CL:0000540\"]):\n", " print(f\" {p} {adapter.label(p)} {o} {adapter.label(o)}\")" ] }, { "cell_type": "code", "execution_count": 18, "id": "e13fd38c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " rdfs:subClassOf FROM: CL:0000028 CNS neuron (sensu Nematoda and Protostomia)\n", " rdfs:subClassOf FROM: CL:0000029 neural crest derived neuron\n", " rdfs:subClassOf FROM: CL:0000099 interneuron\n", " rdfs:subClassOf FROM: CL:0000102 polymodal neuron\n", " rdfs:subClassOf FROM: CL:0000104 multipolar neuron\n", " rdfs:subClassOf FROM: CL:0000105 pseudounipolar neuron\n", " rdfs:subClassOf FROM: CL:0000106 unipolar neuron\n", " rdfs:subClassOf FROM: CL:0000108 cholinergic neuron\n", " rdfs:subClassOf FROM: CL:0000109 adrenergic neuron\n", " rdfs:subClassOf FROM: CL:0000110 peptidergic neuron\n" ] } ], "source": [ "for s, p, _o in list(adapter.relationships(objects=[\"CL:0000540\"]))[0:10]:\n", " print(f\" {p} FROM: {s} {adapter.label(s)}\")" ] }, { "cell_type": "code", "execution_count": 14, "id": "049cfd10", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "BFO:0000002 continuant\n", "BFO:0000004 independent continuant\n", "BFO:0000040 material entity\n", "CARO:0000000 anatomical entity\n", "CARO:0000006 material anatomical entity\n", "CARO:0030000 biological entity\n", "UBERON:0000061 anatomical structure\n", "UBERON:0000465 material anatomical entity\n", "UBERON:0000467 anatomical system\n", "UBERON:0000468 multicellular organism\n", "UBERON:0001016 nervous system\n", "UBERON:0001062 anatomical entity\n", "UBERON:0010000 multicellular anatomical structure\n" ] } ], "source": [ "for _s, _p, o in adapter.relationships([\"CL:0000540\"], predicates=[PART_OF], include_entailed=True):\n", " print(o, adapter.label(o))" ] }, { "cell_type": "markdown", "id": "d478e8fb", "metadata": {}, "source": [ "This includes all the entailed part-of relationships from neuron, including trivial ones (\"every neuron is part of a material entity\")" ] }, { "cell_type": "code", "execution_count": 19, "id": "b52e0519", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CL:0000705 R6 photoreceptor cell\n", "CL:4023108 oxytocin-secreting magnocellular cell\n", "CL:0004240 WF1 amacrine cell\n", "CL:0004242 WF3-1 amacrine cell\n", "CL:1000380 type 1 vestibular sensory cell of epithelium of macula of saccule of membranous labyrinth\n", "CL:1001582 lateral ventricle neuron\n", "CL:4023128 rostral periventricular region of the third ventricle KDNy neuron\n", "CL:0003020 retinal ganglion cell C outer\n", "CL:4023094 tufted pyramidal neuron\n", "CL:4023057 cerebellar inhibitory GABAergic interneuron\n" ] } ], "source": [ "for s, _p, o in list(adapter.relationships(objects=[\"CL:0000540\"], predicates=[IS_A], include_entailed=True))[0:10]:\n", " print(s, adapter.label(s))" ] }, { "cell_type": "markdown", "id": "d07c30cc", "metadata": {}, "source": [ "### Creating a Data Frame for Relationships\n", "\n", "Next we will see how to create a small data frame for relationships for forebrain neurons:" ] }, { "cell_type": "code", "execution_count": 20, "id": "f3afbee7", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | s | \n", "s_label | \n", "p | \n", "p_label | \n", "o | \n", "o_label | \n", "
---|---|---|---|---|---|---|
0 | \n", "CL:1001434 | \n", "olfactory bulb interneuron | \n", "BFO:0000050 | \n", "part of | \n", "UBERON:0002264 | \n", "olfactory bulb | \n", "
1 | \n", "CL:1001434 | \n", "olfactory bulb interneuron | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:0002264 | \n", "olfactory bulb | \n", "
2 | \n", "CL:1001434 | \n", "olfactory bulb interneuron | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0000101 | \n", "sensory neuron | \n", "
3 | \n", "CL:1001434 | \n", "olfactory bulb interneuron | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0000402 | \n", "CNS interneuron | \n", "
4 | \n", "CL:1001434 | \n", "olfactory bulb interneuron | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0012001 | \n", "neuron of the forebrain | \n", "
5 | \n", "CL:1001435 | \n", "periglomerular cell | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:0005377 | \n", "olfactory bulb glomerular layer | \n", "
6 | \n", "CL:1001435 | \n", "periglomerular cell | \n", "rdfs:subClassOf | \n", "None | \n", "CL:1001434 | \n", "olfactory bulb interneuron | \n", "
7 | \n", "CL:1001502 | \n", "mitral cell | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:0004186 | \n", "olfactory bulb mitral cell layer | \n", "
8 | \n", "CL:1001502 | \n", "mitral cell | \n", "rdfs:subClassOf | \n", "None | \n", "CL:1001434 | \n", "olfactory bulb interneuron | \n", "
9 | \n", "CL:1001503 | \n", "olfactory bulb tufted cell | \n", "BFO:0000050 | \n", "part of | \n", "UBERON:0005376 | \n", "olfactory bulb external plexiform layer | \n", "
10 | \n", "CL:1001503 | \n", "olfactory bulb tufted cell | \n", "rdfs:subClassOf | \n", "None | \n", "CARO:0000000 | \n", "anatomical entity | \n", "
11 | \n", "CL:1001503 | \n", "olfactory bulb tufted cell | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0000540 | \n", "neuron | \n", "
12 | \n", "CL:1001505 | \n", "parvocellular neurosecretory cell | \n", "BFO:0000050 | \n", "part of | \n", "UBERON:0001930 | \n", "paraventricular nucleus of hypothalamus | \n", "
13 | \n", "CL:1001505 | \n", "parvocellular neurosecretory cell | \n", "RO:0002215 | \n", "capable of | \n", "GO:0030103 | \n", "vasopressin secretion | \n", "
14 | \n", "CL:1001505 | \n", "parvocellular neurosecretory cell | \n", "rdfs:subClassOf | \n", "None | \n", "CARO:0000000 | \n", "anatomical entity | \n", "
15 | \n", "CL:1001505 | \n", "parvocellular neurosecretory cell | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0000167 | \n", "peptide hormone secreting cell | \n", "
16 | \n", "CL:1001505 | \n", "parvocellular neurosecretory cell | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0000381 | \n", "neurosecretory neuron | \n", "
17 | \n", "CL:1001505 | \n", "parvocellular neurosecretory cell | \n", "rdfs:subClassOf | \n", "None | \n", "CL:2000030 | \n", "hypothalamus cell | \n", "
18 | \n", "CL:1001571 | \n", "hippocampal pyramidal neuron | \n", "BFO:0000050 | \n", "part of | \n", "UBERON:0002313 | \n", "hippocampus pyramidal layer | \n", "
19 | \n", "CL:1001571 | \n", "hippocampal pyramidal neuron | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0002608 | \n", "hippocampal neuron | \n", "
20 | \n", "CL:1001571 | \n", "hippocampal pyramidal neuron | \n", "rdfs:subClassOf | \n", "None | \n", "CL:4023111 | \n", "cerebral cortex pyramidal neuron | \n", "
21 | \n", "CL:4023008 | \n", "intratelencephalic-projecting glutamatergic co... | \n", "RO:0000053 | \n", "bearer of | \n", "PATO:0070034 | \n", "intratelencephalic projecting | \n", "
22 | \n", "CL:4023008 | \n", "intratelencephalic-projecting glutamatergic co... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0000679 | \n", "glutamatergic neuron | \n", "
23 | \n", "CL:4023008 | \n", "intratelencephalic-projecting glutamatergic co... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:0010012 | \n", "cerebral cortex neuron | \n", "
24 | \n", "CL:4023040 | \n", "L2/3-6 intratelencephalic projecting glutamate... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:4023008 | \n", "intratelencephalic-projecting glutamatergic co... | \n", "
25 | \n", "CL:4023047 | \n", "L2/3 intratelencephalic projecting glutamaterg... | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:0001384 | \n", "primary motor cortex | \n", "
26 | \n", "CL:4023047 | \n", "L2/3 intratelencephalic projecting glutamaterg... | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:8440000 | \n", "cortical layer II/III | \n", "
27 | \n", "CL:4023047 | \n", "L2/3 intratelencephalic projecting glutamaterg... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:4023040 | \n", "L2/3-6 intratelencephalic projecting glutamate... | \n", "
28 | \n", "CL:4023048 | \n", "L4/5 intratelencephalic projecting glutamaterg... | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:0001384 | \n", "primary motor cortex | \n", "
29 | \n", "CL:4023048 | \n", "L4/5 intratelencephalic projecting glutamaterg... | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:8440001 | \n", "cortical layer IV/V | \n", "
30 | \n", "CL:4023048 | \n", "L4/5 intratelencephalic projecting glutamaterg... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:4023040 | \n", "L2/3-6 intratelencephalic projecting glutamate... | \n", "
31 | \n", "CL:4023049 | \n", "L5 intratelencephalic projecting glutamatergic... | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:0001384 | \n", "primary motor cortex | \n", "
32 | \n", "CL:4023049 | \n", "L5 intratelencephalic projecting glutamatergic... | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:0005394 | \n", "cortical layer V | \n", "
33 | \n", "CL:4023049 | \n", "L5 intratelencephalic projecting glutamatergic... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:4023040 | \n", "L2/3-6 intratelencephalic projecting glutamate... | \n", "
34 | \n", "CL:4023050 | \n", "L6 intratelencephalic projecting glutamatergic... | \n", "RO:0000053 | \n", "bearer of | \n", "PATO:0070019 | \n", "untufted pyramidal morphology | \n", "
35 | \n", "CL:4023050 | \n", "L6 intratelencephalic projecting glutamatergic... | \n", "RO:0002100 | \n", "has soma location | \n", "UBERON:0005395 | \n", "cortical layer VI | \n", "
36 | \n", "CL:4023050 | \n", "L6 intratelencephalic projecting glutamatergic... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:2000049 | \n", "primary motor cortex pyramidal cell | \n", "
37 | \n", "CL:4023050 | \n", "L6 intratelencephalic projecting glutamatergic... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:4023040 | \n", "L2/3-6 intratelencephalic projecting glutamate... | \n", "
38 | \n", "CL:4023080 | \n", "stellate L6 intratelencephalic projecting glut... | \n", "RO:0000053 | \n", "bearer of | \n", "PATO:0070020 | \n", "stellate pyramidal morphology | \n", "
39 | \n", "CL:4023080 | \n", "stellate L6 intratelencephalic projecting glut... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:4023050 | \n", "L6 intratelencephalic projecting glutamatergic... | \n", "
40 | \n", "CL:4023081 | \n", "inverted L6 intratelencephalic projecting glut... | \n", "RO:0000053 | \n", "bearer of | \n", "PATO:0070021 | \n", "inverted pyramidal morphology | \n", "
41 | \n", "CL:4023081 | \n", "inverted L6 intratelencephalic projecting glut... | \n", "rdfs:subClassOf | \n", "None | \n", "CL:4023050 | \n", "L6 intratelencephalic projecting glutamatergic... | \n", "