{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Meta functionalities of the EpiGraphDB platform" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this notebook we show the following aspects of the EpiGraphDB platform, and how to use the API to get the information:\n", "\n", "1. Metadata: meta nodes and meta edges, and the overall schema.\n", "2. Search for a specific node under the meta node.\n", "3. Cypher: how to query the database directly using Neo4j Cypher\n", "\n", "For detailed documentation on the API endpoints please visit:\n", "\n", "- The Swagger interface: http://api.epigraphdb.org\n", "- The sections regarding API endpoints on the documentation site: http://docs.epigraphdb.org/api/api-endpoints/" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from pprint import pformat\n", "\n", "import networkx as nx\n", "import pandas as pd\n", "import requests" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "API_URL = \"https://api.epigraphdb.org\"\n", "\n", "requests.get(f\"{API_URL}/ping\").json()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Metadata" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we query for the metadata information using the endpoint `GET /meta/schema`, which will be used for downstream processing." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dict_keys(['nodes', 'edges', 'connections']) \n", "\n", "# nodes:\n", "{'Disease': {'count': 21829,\n", " 'properties': {'definition': {'indexed': False,\n", " 'type': 'STRING',\n", " 'unique': False},\n", " 'doid': {'indexed': False,\n", " 'type': 'LIST',\n", " 'unique': False},\n", " 'efo': {'indexed': False,\n", " 'type': 'LIST',\n", " 'unique': False},\n", " 'icd10': {'indexed': False,\n", " 'type': 'LIST',\n", " 'unique': False},\n", " 'icd9': {'indexed': False,\n", " 'type': 'LIST',\n", " 'unique': False},\n", " 'id': {'indexed': True,\n", " 'type': 'STRING',\n", " \n", "\n", "# edges:\n", "{'BN_GEN_COR': {'count': 904832,\n", " 'properties': {'gcov_int': {'array': False, 'type': 'FLOAT'},\n", " 'gcov_int_se': {'array': False, 'type': 'FLOAT'},\n", " 'h2_int': {'array': False, 'type': 'FLOAT'},\n", " 'h2_int_se': {'array': False, 'type': 'FLOAT'},\n", " 'h2_obs': {'array': False, 'type': 'FLOAT'},\n", " 'h2_obs_se': {'array': False, 'type': 'FLOAT'},\n", " 'p': {'array': False, 'type': 'FLOAT'},\n", " 'rg': {'array': False, 'type': 'FLOAT'},\n", " 'se': {'array': False, 'type': 'FLOAT'},\n", " 'z': {'array': False, 'type': 'FLOAT'}}},\n", " 'CPIC': {'count': 355,\n", " 'properties': {'cpic_level': {'array': False, 'type': 'STRING'},\n", " 'guideline': {'array': False, 'type': 'STRING'},\n", " 'pgx_on_fda_ \n", "\n", "# connections:\n", "[{'count': 2486,\n", " 'from_node': 'Drug',\n", " 'rel': 'OPENTARGETS_DRUG_TO_DISEASE',\n", " 'to_node': 'Disease'},\n", " {'count': 3414,\n", " 'from_node': 'Disease',\n", " 'rel': 'MONDO_MAP_UMLS',\n", " 'to_node': 'SemmedTerm'},\n", " {'count': 626,\n", " 'from_node': 'Protein',\n", " 'rel': 'PROTEIN_TO_DISEASE',\n", " 'to_node': 'Disease'},\n", " {'count': 2822,\n", " 'from_node': 'Disease',\n", " 'rel': 'MONDO_MAP_EFO',\n", " 'to_node': 'Efo'},\n", " {'count': 541,\n", " 'from_node': 'Pathway',\n", " 'rel': 'PATHWAY_TO_DISEASE',\n", " 'to_node': 'Disease'},\n", " {'count': 41706,\n", " 'from_node': 'SemmedTerm',\n", " 'rel': 'SEM_GENE',\n", " 'to_node': 'Gene'},\n", " {'count': 3428531,\n", " 'from_node': 'SemmedTriple',\n", " 'rel': 'SEM_SUB',\n", " 'to_node': 'SemmedTerm'},\n", " {'count': 2081,\n", " 'from_node': 'Gwas',\n", " 'rel': 'METAMAP_LITE',\n", " 'to_node': 'SemmedTerm'},\n", " {'count': 3428531,\n", " 'from_node': 'SemmedTerm',\n", " 'rel': 'SEM_PREDICATE',\n", " 'to_node': 'SemmedTerm'},\n", " {'count': 3428531,\n", " 'from_node': 'SemmedTriple',\n", " 'rel': 'SEM_OBJ',\n", " 'to_node': 'SemmedTerm'},\n", " {'count': 12488,\n", " 'from_n \n", "\n" ] } ], "source": [ "endpoint = \"/meta/schema\"\n", "params = {\"graphviz\": False, \"plot\": False}\n", "r = requests.get(f\"{API_URL}{endpoint}\", params=params)\n", "r.raise_for_status()\n", "metadata = r.json()\n", "\n", "# Preview of metadata information\n", "keys = metadata.keys()\n", "print(pformat(keys), \"\\n\")\n", "for key in list(keys):\n", " print(f\"# {key}:\")\n", " print(pformat(metadata[key])[:1000], \"\\n\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Meta nodes\n", "\n", "We can extract the specific meta node information as a pandas dataframe from the metadata." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
countproperties
Disease21,829{'doid': {'type': 'LIST', 'indexed': False, 'u...
Drug2,455{'molecule_type': {'type': 'STRING', 'indexed'...
Efo25,390{'type': {'type': 'STRING', 'indexed': False, ...
Event11,868{'name': {'type': 'STRING', 'indexed': False, ...
Gene59,171{'druggability_tier': {'type': 'STRING', 'inde...
Gwas31,773{'note': {'type': 'STRING', 'indexed': False, ...
Literature29,137,785{'pubmed_id': {'type': 'STRING', 'indexed': Tr...
Pathway2,180{'name': {'type': 'STRING', 'indexed': False, ...
Protein21,543{'uniprot_id': {'type': 'STRING', 'indexed': T...
SemmedTerm103,967{'name': {'type': 'STRING', 'indexed': True, '...
SemmedTriple3,428,531{'subject_id': {'type': 'STRING', 'indexed': F...
Tissue53{'tissue': {'type': 'STRING', 'indexed': True,...
Variant88,176{'name': {'type': 'STRING', 'indexed': True, '...
\n", "
" ], "text/plain": [ " count properties\n", "Disease 21,829 {'doid': {'type': 'LIST', 'indexed': False, 'u...\n", "Drug 2,455 {'molecule_type': {'type': 'STRING', 'indexed'...\n", "Efo 25,390 {'type': {'type': 'STRING', 'indexed': False, ...\n", "Event 11,868 {'name': {'type': 'STRING', 'indexed': False, ...\n", "Gene 59,171 {'druggability_tier': {'type': 'STRING', 'inde...\n", "Gwas 31,773 {'note': {'type': 'STRING', 'indexed': False, ...\n", "Literature 29,137,785 {'pubmed_id': {'type': 'STRING', 'indexed': Tr...\n", "Pathway 2,180 {'name': {'type': 'STRING', 'indexed': False, ...\n", "Protein 21,543 {'uniprot_id': {'type': 'STRING', 'indexed': T...\n", "SemmedTerm 103,967 {'name': {'type': 'STRING', 'indexed': True, '...\n", "SemmedTriple 3,428,531 {'subject_id': {'type': 'STRING', 'indexed': F...\n", "Tissue 53 {'tissue': {'type': 'STRING', 'indexed': True,...\n", "Variant 88,176 {'name': {'type': 'STRING', 'indexed': True, '..." ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "meta_node_df = pd.DataFrame.from_dict(metadata[\"nodes\"], orient=\"index\")\n", "\n", "(\n", " meta_node_df.sort_index().assign(\n", " count=lambda df: df[\"count\"].apply(lambda x: f\"{x:,}\")\n", " )\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Meta relationships and connections\n", "\n", "We can also extract the meta relationship (edge) information, and the connections." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
countpropertiesfrom_nodeto_node
MONDO_MAP_EFO2,822NoneDiseaseEfo
MONDO_MAP_UMLS3,414NoneDiseaseSemmedTerm
OPENTARGETS_DRUG_TO_DISEASE2,486NoneDrugDisease
CPIC355{'pharmgkb_level_of_evidence': {'array': False...DrugGene
OPENTARGETS_DRUG_TO_TARGET6,024{'phase': {'array': False, 'type': 'STRING'}, ...DrugGene
EFO_CHILD_OF43,154NoneEfoEfo
PRECEDING_EVENT10,418NoneEventEvent
INTACT_INTERACTS_WITH_GENE_GENE2{'intact_confidence_score': {'array': False, '...GeneGene
XQTL_MULTI_SNP_MR3,098,049{'p': {'array': False, 'type': 'FLOAT'}, 'se':...GeneGwas
XQTL_SINGLE_SNP_MR_GENE_GWAS8,703,863{'p': {'array': False, 'type': 'FLOAT'}, 'rsid...GeneGwas
GENE_TO_LITERATURE771NoneGeneLiterature
INTACT_INTERACTS_WITH_GENE_PROTEIN1,451{'intact_confidence_score': {'array': False, '...GeneProtein
GENE_TO_PROTEIN20,762NoneGeneProtein
EXPRESSED_IN861,552{'tpm': {'array': False, 'type': 'FLOAT'}}GeneTissue
GWAS_NLP_EFO6,936{'score': {'array': False, 'type': 'FLOAT'}}GwasEfo
BN_GEN_COR904,832{'p': {'array': False, 'type': 'FLOAT'}, 'se':...GwasGwas
PRS132,703{'p': {'array': False, 'type': 'FLOAT'}, 'r2':...GwasGwas
MR583,619{'b': {'array': False, 'type': 'FLOAT'}, 'se':...GwasGwas
OBS_COR17,932{'cor': {'array': False, 'type': 'FLOAT'}}GwasGwas
GWAS_NLP30,838,964{'score': {'array': False, 'type': 'FLOAT'}}GwasGwas
GWAS_TO_LIT19,079,468NoneGwasLiterature
METAMAP_LITE2,081{'mmi_score': {'array': False, 'type': 'FLOAT'}}GwasSemmedTerm
GWAS_SEM9,075,020{'globalTotal': {'array': False, 'type': 'INTE...GwasSemmedTriple
TOPHITS122,730{'pval': {'array': False, 'type': 'FLOAT'}, 'b...GwasVariant
GWAS_TO_VARIANT26,521{'se': {'array': False, 'type': 'FLOAT'}, 'nca...GwasVariant
PATHWAY_TO_DISEASE541NonePathwayDisease
EVENT_IN_PATHWAY12,488NonePathwayEvent
PATHWAY_TO_LITERATURE8,952NonePathwayLiterature
PROTEIN_TO_DISEASE626NoneProteinDisease
PROTEIN_IN_EVENT13,484NoneProteinEvent
PROTEIN_TO_LITERATURE107,315NoneProteinLiterature
PROTEIN_IN_PATHWAY9,955NoneProteinPathway
INTACT_NOT_INTERACTS_WITH699{'intact_confidence_score': {'array': False, '...ProteinProtein
STRING_INTERACT_WITH390,222{'score': {'array': False, 'type': 'INTEGER'}}ProteinProtein
INTACT_INTERACTS_WITH_PROTEIN_PROTEIN187,426{'intact_confidence_score': {'array': False, '...ProteinProtein
SEM_GENE41,706NoneSemmedTermGene
SEM_PREDICATE3,428,531{'count': {'array': False, 'type': 'INTEGER'},...SemmedTermSemmedTerm
SEM_TO_LIT6,127,985NoneSemmedTripleLiterature
SEM_OBJ3,428,531NoneSemmedTripleSemmedTerm
SEM_SUB3,428,531NoneSemmedTripleSemmedTerm
VARIANT_TO_GENE59,157{'feature_type': {'array': False, 'type': 'STR...VariantGene
XQTL_SINGLE_SNP_MR_SNP_GENE41,564NoneVariantGene
\n", "
" ], "text/plain": [ " count \\\n", "MONDO_MAP_EFO 2,822 \n", "MONDO_MAP_UMLS 3,414 \n", "OPENTARGETS_DRUG_TO_DISEASE 2,486 \n", "CPIC 355 \n", "OPENTARGETS_DRUG_TO_TARGET 6,024 \n", "EFO_CHILD_OF 43,154 \n", "PRECEDING_EVENT 10,418 \n", "INTACT_INTERACTS_WITH_GENE_GENE 2 \n", "XQTL_MULTI_SNP_MR 3,098,049 \n", "XQTL_SINGLE_SNP_MR_GENE_GWAS 8,703,863 \n", "GENE_TO_LITERATURE 771 \n", "INTACT_INTERACTS_WITH_GENE_PROTEIN 1,451 \n", "GENE_TO_PROTEIN 20,762 \n", "EXPRESSED_IN 861,552 \n", "GWAS_NLP_EFO 6,936 \n", "BN_GEN_COR 904,832 \n", "PRS 132,703 \n", "MR 583,619 \n", "OBS_COR 17,932 \n", "GWAS_NLP 30,838,964 \n", "GWAS_TO_LIT 19,079,468 \n", "METAMAP_LITE 2,081 \n", "GWAS_SEM 9,075,020 \n", "TOPHITS 122,730 \n", "GWAS_TO_VARIANT 26,521 \n", "PATHWAY_TO_DISEASE 541 \n", "EVENT_IN_PATHWAY 12,488 \n", "PATHWAY_TO_LITERATURE 8,952 \n", "PROTEIN_TO_DISEASE 626 \n", "PROTEIN_IN_EVENT 13,484 \n", "PROTEIN_TO_LITERATURE 107,315 \n", "PROTEIN_IN_PATHWAY 9,955 \n", "INTACT_NOT_INTERACTS_WITH 699 \n", "STRING_INTERACT_WITH 390,222 \n", "INTACT_INTERACTS_WITH_PROTEIN_PROTEIN 187,426 \n", "SEM_GENE 41,706 \n", "SEM_PREDICATE 3,428,531 \n", "SEM_TO_LIT 6,127,985 \n", "SEM_OBJ 3,428,531 \n", "SEM_SUB 3,428,531 \n", "VARIANT_TO_GENE 59,157 \n", "XQTL_SINGLE_SNP_MR_SNP_GENE 41,564 \n", "\n", " properties \\\n", "MONDO_MAP_EFO None \n", "MONDO_MAP_UMLS None \n", "OPENTARGETS_DRUG_TO_DISEASE None \n", "CPIC {'pharmgkb_level_of_evidence': {'array': False... \n", "OPENTARGETS_DRUG_TO_TARGET {'phase': {'array': False, 'type': 'STRING'}, ... \n", "EFO_CHILD_OF None \n", "PRECEDING_EVENT None \n", "INTACT_INTERACTS_WITH_GENE_GENE {'intact_confidence_score': {'array': False, '... \n", "XQTL_MULTI_SNP_MR {'p': {'array': False, 'type': 'FLOAT'}, 'se':... \n", "XQTL_SINGLE_SNP_MR_GENE_GWAS {'p': {'array': False, 'type': 'FLOAT'}, 'rsid... \n", "GENE_TO_LITERATURE None \n", "INTACT_INTERACTS_WITH_GENE_PROTEIN {'intact_confidence_score': {'array': False, '... \n", "GENE_TO_PROTEIN None \n", "EXPRESSED_IN {'tpm': {'array': False, 'type': 'FLOAT'}} \n", "GWAS_NLP_EFO {'score': {'array': False, 'type': 'FLOAT'}} \n", "BN_GEN_COR {'p': {'array': False, 'type': 'FLOAT'}, 'se':... \n", "PRS {'p': {'array': False, 'type': 'FLOAT'}, 'r2':... \n", "MR {'b': {'array': False, 'type': 'FLOAT'}, 'se':... \n", "OBS_COR {'cor': {'array': False, 'type': 'FLOAT'}} \n", "GWAS_NLP {'score': {'array': False, 'type': 'FLOAT'}} \n", "GWAS_TO_LIT None \n", "METAMAP_LITE {'mmi_score': {'array': False, 'type': 'FLOAT'}} \n", "GWAS_SEM {'globalTotal': {'array': False, 'type': 'INTE... \n", "TOPHITS {'pval': {'array': False, 'type': 'FLOAT'}, 'b... \n", "GWAS_TO_VARIANT {'se': {'array': False, 'type': 'FLOAT'}, 'nca... \n", "PATHWAY_TO_DISEASE None \n", "EVENT_IN_PATHWAY None \n", "PATHWAY_TO_LITERATURE None \n", "PROTEIN_TO_DISEASE None \n", "PROTEIN_IN_EVENT None \n", "PROTEIN_TO_LITERATURE None \n", "PROTEIN_IN_PATHWAY None \n", "INTACT_NOT_INTERACTS_WITH {'intact_confidence_score': {'array': False, '... \n", "STRING_INTERACT_WITH {'score': {'array': False, 'type': 'INTEGER'}} \n", "INTACT_INTERACTS_WITH_PROTEIN_PROTEIN {'intact_confidence_score': {'array': False, '... \n", "SEM_GENE None \n", "SEM_PREDICATE {'count': {'array': False, 'type': 'INTEGER'},... \n", "SEM_TO_LIT None \n", "SEM_OBJ None \n", "SEM_SUB None \n", "VARIANT_TO_GENE {'feature_type': {'array': False, 'type': 'STR... \n", "XQTL_SINGLE_SNP_MR_SNP_GENE None \n", "\n", " from_node to_node \n", "MONDO_MAP_EFO Disease Efo \n", "MONDO_MAP_UMLS Disease SemmedTerm \n", "OPENTARGETS_DRUG_TO_DISEASE Drug Disease \n", "CPIC Drug Gene \n", "OPENTARGETS_DRUG_TO_TARGET Drug Gene \n", "EFO_CHILD_OF Efo Efo \n", "PRECEDING_EVENT Event Event \n", "INTACT_INTERACTS_WITH_GENE_GENE Gene Gene \n", "XQTL_MULTI_SNP_MR Gene Gwas \n", "XQTL_SINGLE_SNP_MR_GENE_GWAS Gene Gwas \n", "GENE_TO_LITERATURE Gene Literature \n", "INTACT_INTERACTS_WITH_GENE_PROTEIN Gene Protein \n", "GENE_TO_PROTEIN Gene Protein \n", "EXPRESSED_IN Gene Tissue \n", "GWAS_NLP_EFO Gwas Efo \n", "BN_GEN_COR Gwas Gwas \n", "PRS Gwas Gwas \n", "MR Gwas Gwas \n", "OBS_COR Gwas Gwas \n", "GWAS_NLP Gwas Gwas \n", "GWAS_TO_LIT Gwas Literature \n", "METAMAP_LITE Gwas SemmedTerm \n", "GWAS_SEM Gwas SemmedTriple \n", "TOPHITS Gwas Variant \n", "GWAS_TO_VARIANT Gwas Variant \n", "PATHWAY_TO_DISEASE Pathway Disease \n", "EVENT_IN_PATHWAY Pathway Event \n", "PATHWAY_TO_LITERATURE Pathway Literature \n", "PROTEIN_TO_DISEASE Protein Disease \n", "PROTEIN_IN_EVENT Protein Event \n", "PROTEIN_TO_LITERATURE Protein Literature \n", "PROTEIN_IN_PATHWAY Protein Pathway \n", "INTACT_NOT_INTERACTS_WITH Protein Protein \n", "STRING_INTERACT_WITH Protein Protein \n", "INTACT_INTERACTS_WITH_PROTEIN_PROTEIN Protein Protein \n", "SEM_GENE SemmedTerm Gene \n", "SEM_PREDICATE SemmedTerm SemmedTerm \n", "SEM_TO_LIT SemmedTriple Literature \n", "SEM_OBJ SemmedTriple SemmedTerm \n", "SEM_SUB SemmedTriple SemmedTerm \n", "VARIANT_TO_GENE Variant Gene \n", "XQTL_SINGLE_SNP_MR_SNP_GENE Variant Gene " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "meta_rel_df = pd.DataFrame.from_dict(metadata[\"edges\"], orient=\"index\").merge(\n", " pd.DataFrame.from_dict(\n", " {_[\"rel\"]: _ for _ in metadata[\"connections\"]}, orient=\"index\"\n", " )[[\"from_node\", \"to_node\"]],\n", " left_index=True,\n", " right_index=True,\n", ")\n", "\n", "(\n", " meta_rel_df.sort_values(by=[\"from_node\", \"to_node\"]).assign(\n", " count=lambda df: df[\"count\"].apply(lambda x: f\"{x:,}\")\n", " )\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Schema plot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can generate a network diagram of the graph db schema using `networkx`." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "graph = nx.from_pandas_edgelist(\n", " meta_rel_df, source=\"from_node\", target=\"to_node\"\n", ")" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "nx.draw(\n", " G=graph,\n", " pos=nx.kamada_kawai_layout(graph),\n", " with_labels=True,\n", " node_color=\"white\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A detailed version of the shema plot can be obtained from the API:\n", "\n", "![schema_plot](http://ieu-mrbssd1.epi.bris.ac.uk:28046/meta/schema?graphviz=true&plot=true)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Search for specific node" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Users can use [the explorer on the Web UI](http://dev.epigraphdb.org/explore) to search for a specific node by:\n", "\n", "- fuzzy matching by \"name\" field.\n", "- exact matching by \"ID\" field if you know the its ID (e.g. the ID to a GWAS from IEU GWAS Database).\n", "\n", "Here we show how these are done at the API level using `Gwas` nodes as an example." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we need to know what the \"ID\" and \"name\" fields are for the meta nodes using `GET /meta/nodes/id-name-schema`:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Disease': {'id': 'id', 'name': 'label'},\n", " 'Drug': {'id': 'label', 'name': 'label'},\n", " 'Efo': {'id': 'id', 'name': 'value'},\n", " 'Event': {'id': 'reactome_id', 'name': 'name'},\n", " 'Gene': {'id': 'ensembl_id', 'name': 'name'},\n", " 'Tissue': {'id': 'tissue', 'name': 'tissue'},\n", " 'Gwas': {'id': 'id', 'name': 'trait'},\n", " 'Literature': {'id': 'pubmed_id', 'name': 'pubmed_id'},\n", " 'Pathway': {'id': 'reactome_id', 'name': 'name'},\n", " 'Protein': {'id': 'uniprot_id', 'name': 'uniprot_id'},\n", " 'SemmedTerm': {'id': 'id', 'name': 'name'},\n", " 'Variant': {'id': 'name', 'name': 'name'}}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "r = requests.get(f\"{API_URL}/meta/nodes/id-name-schema\")\n", "r.raise_for_status()\n", "\n", "meta_node_fields = r.json()\n", "meta_node_fields" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Fuzzy matching" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we search for nodes can contain \"body mass index\" in their traits." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'metadata': {'empty_results': False,\n", " 'query': 'MATCH (node: Gwas) WHERE node.trait =~ \"(?i).*body '\n", " 'mass index.*\" RETURN node LIMIT 10;',\n", " 'total_seconds': 0.009114},\n", " 'results': [{'node': {'access': 'public',\n", " 'author': 'Hoffmann TJ',\n", " 'category': 'NA',\n", " 'consortium': 'NA',\n", " 'id': 'ebi-a-GCST006368',\n", " 'mr': '1',\n", " 'note': 'NA',\n", " 'nsnp': '27854527',\n", " 'pmid': '30108127',\n", " 'population': 'European',\n", " 'priority': '0',\n", " 'sample_size': '315347',\n", " 'sex': 'NA',\n", " 'subcategory': 'NA',\n", " 'trait': 'Body mass index',\n", " 'unit': 'NA',\n", " 'year': '2018'}},\n", " {'node': {'access': 'public',\n", " 'author': 'Locke AE',\n", " 'category': 'Risk factor',\n", " 'consortium': 'NA',\n", " 'id': 'ieu-a-2',\n", " 'mr': '1',\n", " 'nsnp': '2555511',\n", " 'pmid': '25673413',\n", " 'population': 'Mixed',\n", " 'priority': '1',\n", " 'sample_size': '339224',\n", " 'sd': '4.77',\n", " 'sex': 'Males and Females',\n", " 'subcategory': 'Anthropometric',\n", " 'trait': 'Body mass index',\n", " 'unit': 'NA',\n", " 'year': '2015'}},\n", " {'node': {'access': 'public',\n", " 'author': 'Locke AE',\n", " 'category': 'Risk factor',\n", " 'consortium': 'NA',\n", " 'id': 'ieu-a-785',\n", " 'mr': '1',\n", " 'nsnp': '2477659',\n", " 'pmid': '25673413',\n", " 'population': 'European',\n", " 'priority': '2',\n", " 'sample_size': '152893',\n", " 'sd': '4.77',\n", " 'sex': 'Males',\n", " 'subcategory': 'Anthropometric',\n", " 'trait': 'Body mass index',\n", " 'unit': 'NA',\n", " 'year': '2015'}},\n", " {'node': {'access': 'public',\n", " 'author': 'Locke AE',\n", " 'category': 'Risk factor',\n", " 'consortium': 'NA',\n", " 'id': 'ieu-a-835',\n", " 'mr': '1',\n", " 'nsnp': '2554668',\n", " 'pmid': '25673413',\n", " 'population': 'European',\n", " 'priority': '3',\n", " 'sample_size': '322154',\n", " 'sd': '4.77',\n", " 'sex': 'Males and Females',\n", "\n" ] } ], "source": [ "name = \"body mass index\"\n", "\n", "r = requests.get(f\"{API_URL}/meta/nodes/Gwas/search\", params={\"name\": name})\n", "r.raise_for_status()\n", "\n", "print(pformat(r.json())[:3000])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exact matching" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, we can exact match a specific node by its ID." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'metadata': {'empty_results': False,\n", " 'query': 'MATCH (node: Gwas {id: \"ieu-a-2\"}) RETURN node LIMIT '\n", " '10;',\n", " 'total_seconds': 0.002578},\n", " 'results': [{'node': {'access': 'public',\n", " 'author': 'Locke AE',\n", " 'category': 'Risk factor',\n", " 'consortium': 'NA',\n", " 'id': 'ieu-a-2',\n", " 'mr': '1',\n", " 'nsnp': '2555511',\n", " 'pmid': '25673413',\n", " 'population': 'Mixed',\n", " 'priority': '1',\n", " 'sample_size': '339224',\n", " 'sd': '4.77',\n", " 'sex': 'Males and Females',\n", " 'subcategory': 'Anthropometric',\n", " 'trait': 'Body mass index',\n", " 'unit': 'NA',\n", " 'year': '2015'}}]}\n" ] } ], "source": [ "id = \"ieu-a-2\"\n", "\n", "r = requests.get(f\"{API_URL}/meta/nodes/Gwas/search\", params={\"id\": id})\n", "r.raise_for_status()\n", "\n", "print(pformat(r.json())[:3000])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cypher (advanced)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Advanced users that are familiar with Neo4j Cypher can query the database using Cypher directly." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'metadata': {'empty_results': False,\n", " 'query': 'MATCH (exposure:Gwas)-[mr:MR]->(outcome:Gwas) WHERE '\n", " 'exposure.trait = \"Body mass index\" RETURN exposure, '\n", " 'outcome, mr LIMIT 2',\n", " 'total_seconds': 0.049648},\n", " 'results': [{'exposure': {'access': 'public',\n", " 'author': 'Locke AE',\n", " 'category': 'Risk factor',\n", " 'consortium': 'NA',\n", " 'id': 'ieu-a-2',\n", " 'mr': '1',\n", " 'nsnp': '2555511',\n", " 'pmid': '25673413',\n", " 'population': 'Mixed',\n", " 'priority': '1',\n", " 'sample_size': '339224',\n", " 'sd': '4.77',\n", " 'sex': 'Males and Females',\n", " 'subcategory': 'Anthropometric',\n", " 'trait': 'Body mass index',\n", " 'unit': 'NA',\n", " 'year': '2015'},\n", " 'mr': {'b': 0.0030348598957061768,\n", " 'ci_low': -0.002742477459833026,\n", " 'ci_upp': 0.008812196552753448,\n", " 'log10pval': 1.0,\n", " 'method': 'Weighted median',\n", " 'moescore': 0.7799999713897705,\n", " 'nsnp': 77,\n", " 'pval': 0.3032084107398987,\n", " 'se': 0.002947675297036767,\n", " 'selection': 'DF + HF'},\n", " 'outcome': {'access': 'public',\n", " 'author': 'Neale',\n", " 'category': 'NA',\n", " 'consortium': 'Neale Lab',\n", " 'id': 'ukb-a-99',\n", " 'mr': '1',\n", " 'ncase': '8718',\n", " 'ncontrol': '328441',\n", " 'note': 'NA',\n", " 'nsnp': '10894596',\n", " 'population': 'European',\n", " 'priority': '1',\n", " 'sample_size': '337159',\n", " 'sex': 'Males and Females',\n", " 'subcategory': 'NA',\n", " 'trait': 'Non-cancer illness code self-reported: '\n", " 'eczema/dermatitis',\n", " 'unit': 'SD',\n", " 'year': '2017'}},\n", " {'exposure': {'access': 'public',\n", " 'author': 'Locke AE',\n", " 'category': 'Risk factor',\n", " 'consortium': 'NA',\n", " 'id': 'ieu-a-2',\n", " 'mr': '1',\n", " 'nsnp': '2555511',\n", " 'pmid': '25673413',\n", " 'population': 'Mixed',\n", " 'priority': '1',\n", " 'sample_size': '339224',\n", "\n" ] } ], "source": [ "query = \"\"\"\n", " MATCH (exposure:Gwas)-[mr:MR]->(outcome:Gwas) \n", " WHERE exposure.trait = \"Body mass index\"\n", " RETURN exposure, outcome, mr LIMIT 2\n", "\"\"\"\n", "\n", "r = requests.post(f\"{API_URL}/cypher\", json={\"query\": query})\n", "r.raise_for_status()\n", "\n", "print(pformat(r.json())[:3000])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively we provide an endpoint `POST /cypher/builder/plain` that assist users in querying for simple cypher queries." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'metadata': {'empty_results': False,\n", " 'query': 'MATCH (source_node:Gwas) -[rel:MR]- (target_node:Gwas) '\n", " \"WHERE source_node.trait = 'Body mass index' RETURN \"\n", " 'source_node, rel, target_node LIMIT 2',\n", " 'total_seconds': 0.035151},\n", " 'results': [{'rel': {'b': 0.0030348598957061768,\n", " 'ci_low': -0.002742477459833026,\n", " 'ci_upp': 0.008812196552753448,\n", " 'log10pval': 1.0,\n", " 'method': 'Weighted median',\n", " 'moescore': 0.7799999713897705,\n", " 'nsnp': 77,\n", " 'pval': 0.3032084107398987,\n", " 'se': 0.002947675297036767,\n", " 'selection': 'DF + HF'},\n", " 'source_node': {'access': 'public',\n", " 'author': 'Locke AE',\n", " 'category': 'Risk factor',\n", " 'consortium': 'NA',\n", " 'id': 'ieu-a-2',\n", " 'mr': '1',\n", " 'nsnp': '2555511',\n", " 'pmid': '25673413',\n", " 'population': 'Mixed',\n", " 'priority': '1',\n", " 'sample_size': '339224',\n", " 'sd': '4.77',\n", " 'sex': 'Males and Females',\n", " 'subcategory': 'Anthropometric',\n", " 'trait': 'Body mass index',\n", " 'unit': 'NA',\n", " 'year': '2015'},\n", " 'target_node': {'access': 'public',\n", " 'author': 'Neale',\n", " 'category': 'NA',\n", " 'consortium': 'Neale Lab',\n", " 'id': 'ukb-a-99',\n", " 'mr': '1',\n", " 'ncase': '8718',\n", " 'ncontrol': '328441',\n", " 'note': 'NA',\n", " 'nsnp': '10894596',\n", " 'population': 'European',\n", " 'priority': '1',\n", " 'sample_size': '337159',\n", " 'sex': 'Males and Females',\n", " 'subcategory': 'NA',\n", " 'trait': 'Non-cancer illness code '\n", " 'self-reported: eczema/dermatitis',\n", " 'unit': 'SD',\n", " 'year': '2017'}},\n", " {'rel': {'b': -3.053751788684167e-05,\n", " 'ci_low': -0.00041146361036226153,\n", " 'ci_upp': 0.00035038855276070535,\n", " 'log10pval': 0.0,\n", " 'method': 'RE IVW',\n", " 'moescore': 0.800000011920929,\n", " 'nsnp': 79,\n", " 'pval'\n" ] } ], "source": [ "payload = {\n", " \"source_meta_node\": \"Gwas\",\n", " \"target_meta_node\": \"Gwas\",\n", " \"meta_rel\": \"MR\",\n", " \"where\": [\"source_node.trait = 'Body mass index'\"],\n", " \"limit\": 2,\n", "}\n", "\n", "r = requests.post(f\"{API_URL}/cypher/builder/plain\", json=payload)\n", "r.raise_for_status()\n", "\n", "print(pformat(r.json())[:3000])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again for the detailed documentation on the API endpoints please visit:\n", "\n", "- The Swagger interface: http://api.epigraphdb.org\n", "- The sections regarding API endpoints on the documentation site: http://docs.epigraphdb.org/api/api-endpoints/" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" }, "toc-autonumbering": false }, "nbformat": 4, "nbformat_minor": 4 }