{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# This notebook is used to find a network from a list of nodes in Translator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from TCT import name_resolver\n",
    "from TCT import translator_metakg\n",
    "from TCT import translator_kpinfo\n",
    "from TCT import translator_query\n",
    "from TCT import TCT\n",
    "\n",
    "import pandas as pd\n",
    "import networkx as nx\n",
    "import ipycytoscape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_translator_resources():\n",
    "    \"\"\"\n",
    "    Load the necessary resources for the Translator.\n",
    "    \"\"\"\n",
    "    Translator_KP_info,APInames= translator_kpinfo.get_translator_kp_info()\n",
    "    metaKG = translator_metakg.get_KP_metadata(APInames) \n",
    "    APInames,metaKG = translator_metakg.add_plover_API(APInames, metaKG)\n",
    "    return  APInames, metaKG, Translator_KP_info\n",
    "\n",
    "\n",
    "def visualize_interaction_network(result_json):\n",
    "    \"\"\"\n",
    "    Visualize the interaction network from the result JSON.\n",
    "\n",
    "    Parameters:\n",
    "    result_json (dict): The result JSON containing subjects, objects, and predicates.\n",
    "    \n",
    "    \"\"\"\n",
    "\n",
    "    subjects = []\n",
    "    objects = []\n",
    "    predicates = []\n",
    "\n",
    "    for k, v in result_json.items():\n",
    "        subjects.append(v['subject'])\n",
    "        objects.append(v['object'])\n",
    "        predicates.append(v['predicate'])\n",
    "\n",
    "    # Convert subject and object CURIEs to names using lookup\n",
    "    subject_names = []\n",
    "    object_names = []\n",
    "\n",
    "    # Use batch_lookup for all subjects and objects to minimize API calls\n",
    "    unique_nodes = set(subjects + objects)\n",
    "    node_info_dict = name_resolver.batch_lookup(list(unique_nodes))\n",
    "    print(node_info_dict)\n",
    "\n",
    "    for subj, obj in zip(subjects, objects):\n",
    "        subj_info = node_info_dict.get(subj)\n",
    "        obj_info = node_info_dict.get(obj)\n",
    "        subject_names.append(subj_info.name if subj_info and hasattr(subj_info, 'name') else subj)\n",
    "        object_names.append(obj_info.name if obj_info and hasattr(obj_info, 'name') else obj)\n",
    "\n",
    "\n",
    "    df = pd.DataFrame({\n",
    "        \"Subject\": subject_names,\n",
    "        \"Object\": object_names,\n",
    "        \"Predicate\": predicates,\n",
    "    })\n",
    "\n",
    "    print(df.head())\n",
    "    # merge predicates and sources\n",
    "    # Convert 'Sources' to a string representation\n",
    "    # Remove duplicate edges\n",
    "    df = df.drop_duplicates()\n",
    "\n",
    "    # Build networkx graph\n",
    "    G1 = nx.from_pandas_edgelist(df, source='Subject', target='Object', edge_attr=['Predicate'], create_using=nx.MultiGraph)\n",
    "\n",
    "    # Cytoscape style\n",
    "    graph_style = [\n",
    "        {'selector': 'node', 'style': {'background-color': 'lightblue', 'shape': 'ellipse', 'label': 'data(id)', 'font-size': '12px'}},\n",
    "        {'selector': 'edge', 'style': {'label': 'data(Predicate)', 'font-size': '10px', \"curve-style\": \"bezier\"}}\n",
    "    ]\n",
    "\n",
    "    cyto_graph = ipycytoscape.CytoscapeWidget()\n",
    "    cyto_graph.graph.add_graph_from_networkx(G1, directed=True)\n",
    "    cyto_graph.set_style(graph_style)\n",
    "    cyto_graph.set_layout(name='cose', nodeSpacing=80, edgeLengthVal=50)\n",
    "\n",
    "    display(cyto_graph)\n",
    "\n",
    "    return df\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [],
   "source": [
    "APInames, metaKG, Translator_KP_info= load_translator_resources()\n",
    "\n",
    "All_predicates = list(set(metaKG['Predicate']))\n",
    "All_categories = list((set(list(set(metaKG['Subject']))+list(set(metaKG['Object'])))))\n",
    "API_withMetaKG = list(set(metaKG['API']))\n",
    "\n",
    "    # generate a dictionary of API and its predicates\n",
    "API_predicates = {}\n",
    "for api in API_withMetaKG:\n",
    "    API_predicates[api] = list(set(metaKG[metaKG['API'] == api]['Predicate']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "all relevant predicates in Translator:\n",
      "['biolink:coexists_with', 'biolink:has_participant', 'biolink:disrupts', 'biolink:same_as', 'biolink:acts_upstream_of_or_within', 'biolink:treats_or_applied_or_studied_to_treat', 'biolink:similar_to', 'biolink:chemically_similar_to', 'biolink:correlated_with', 'biolink:response_affected_by', 'biolink:affects_response_to', 'biolink:genetically_associated_with', 'biolink:negatively_correlated_with', 'biolink:decreases_response_to', 'biolink:related_to', 'biolink:physical_interacts_with', 'biolink:overlaps', 'biolink:transcribed_from', 'biolink:has_gene_product', 'biolink:GeneAffectsChemicalAssociation', 'biolink:associated_with_increased_likelihood_of', 'biolink:interacts_with', 'biolink:part_of', 'biolink:orthologous_to', 'biolink:affects', 'biolink:gene_product_of', 'biolink:physically_interacts_with', 'biolink:subclass_of', 'biolink:derives_into', 'biolink:preventative_for_condition', 'biolink:regulated_by', 'biolink:contraindicated_in', 'biolink:causes', 'biolink:derives_from', 'biolink:genetically_interacts_with', 'biolink:expressed_in', 'biolink:associated_with_sensitivity_to', 'biolink:associated_with_resistance_to', 'biolink:occurs_in', 'biolink:affected_by', 'biolink:regulates', 'biolink:colocalizes_with', 'biolink:has_part', 'biolink:translates_to', 'biolink:in_complex_with', 'biolink:associated_with', 'biolink:occurs_together_in_literature_with', 'biolink:directly_physically_interacts_with', 'biolink:has_member', 'biolink:composed_primarily_of', 'biolink:produces', 'biolink:homologous_to', 'biolink:located_in', 'biolink:produced_by', 'biolink:gene_associated_with_condition', 'biolink:capable_of', 'biolink:biomarker_for', 'biolink:increases_response_to', 'biolink:has_phenotype', 'biolink:is_sequence_variant_of', 'biolink:close_match', 'biolink:positively_correlated_with', 'biolink:target_for', 'biolink:has_input', 'biolink:coexpressed_with']\n",
      "all relevant APIs in Translator:\n",
      "['Service Provider TRAPI', 'Automat-pharos(Trapi v1.5.0)', 'RTX KG2 - TRAPI 1.5.0', 'Automat-ehr-clinical-connections-kp(Trapi v1.5.0)', 'MolePro', 'SPOKE KP for TRAPI 1.5', 'Automat-icees-kg(Trapi v1.5.0)', 'Microbiome KP - TRAPI 1.5.0', 'Automat-robokop(Trapi v1.5.0)', 'CATRAX Pharmacogenomics KP - TRAPI 1.5.0', 'Connections Hypothesis Provider API', 'Multiomics KP - TRAPI 1.5.0', 'Automat-ehr-may-treat-kp(Trapi v1.5.0)', 'Text Mined Cooccurrence API', 'Automat-genome-alliance(Trapi v1.5.0)', 'Automat-hetionet(Trapi v1.5.0)', 'Automat-cam-kp(Trapi v1.5.0)', 'BioThings Explorer (BTE) TRAPI', 'CATRAX BigGIM DrugResponse Performance Phase KP - TRAPI 1.5.0', 'Automat-monarchinitiative(Trapi v1.5.0)', 'imProving Agent for TRAPI 1.5']\n",
      "21\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "['https://bte.transltr.io/v1/team/Service%20Provider/query/',\n",
       " 'https://automat.transltr.io/pharos/query/',\n",
       " 'https://kg2cploverdb.ci.transltr.io/kg2c/query',\n",
       " 'https://automat.renci.org/ehr-clinical-connections-kp/query/',\n",
       " 'https://molepro-trapi.transltr.io/molepro/trapi/v1.5/query/',\n",
       " 'https://spokekp.transltr.io/api/v1.5/query/',\n",
       " 'https://automat.transltr.io/icees-kg/query/',\n",
       " 'https://multiomics.rtx.ai:9990/mbkp/query',\n",
       " 'https://automat.transltr.io/robokopkg/query/',\n",
       " 'https://multiomics.rtx.ai:9990/PharmacogenomicsKG/query',\n",
       " 'https://chp-api.transltr.io/query/',\n",
       " 'https://multiomics.rtx.ai:9990/multiomics/query',\n",
       " 'https://automat.renci.org/ehr-may-treat-kp/query/',\n",
       " 'https://cooccurrence.transltr.io/query/',\n",
       " 'https://automat.transltr.io/genome-alliance/query/',\n",
       " 'https://automat.transltr.io/hetio/query/',\n",
       " 'https://automat.transltr.io/cam-kp/query/',\n",
       " 'https://bte.transltr.io/v1/query/',\n",
       " 'https://multiomics.rtx.ai:9990/BigGIM_DrugResponse_PerformancePhase/query',\n",
       " 'https://automat.transltr.io/monarch-kg/query/',\n",
       " 'https://ia.transltr.io/api/v1.5/query/']"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# input_nodes\n",
    "input_list = ['NPM1', 'FLT3', 'NRAS', 'BCL2', 'WNT7B']\n",
    "input_info = name_resolver.batch_lookup(input_list)\n",
    "input_node1_list = [] # get the curie of the nodes in the input_info dictionary\n",
    "input_node1_list = [input_info[node].curie for node in input_list]\n",
    "input_node1_category = []\n",
    "for node in input_list:\n",
    "    if hasattr(input_info[node], 'types'):\n",
    "        input_node1_category = input_node1_category + input_info[node].types\n",
    "input_node1_category = list(set(input_node1_category))\n",
    "\n",
    "# query nodes\n",
    "input_node2_list = []\n",
    "input_node2_category = ['biolink:Gene', 'biolink:Protein', 'biolink:ChemicalSubstance', 'biolink:Drug', 'biolink:DiseaseOrPhenotypicFeature']\n",
    "\n",
    "sele_predicates = list(set(TCT.select_concept(sub_list=input_node1_category,obj_list=input_node2_category,metaKG=metaKG)))\n",
    "print(\"all relevant predicates in Translator:\")\n",
    "print(sele_predicates)\n",
    "\n",
    "\n",
    "# Get all APIs for the input node1 and node2, user can furter select the APIs among this list\n",
    "sele_APIs = TCT.select_API(sub_list=input_node1_category,obj_list=input_node2_category,metaKG=metaKG)\n",
    "print(\"all relevant APIs in Translator:\")\n",
    "print(sele_APIs)\n",
    "print(len(sele_APIs))\n",
    "\n",
    "#sele_APIs = ['Multiomics BigGIM-DrugResponse KP API']\n",
    "sele_APIs = sele_APIs\n",
    "# get API URLs : two options: filter by API names or filter by predicates\n",
    "API_URLs = TCT.get_Translator_API_URL(sele_APIs, \n",
    "                                      APInames)\n",
    "\n",
    "API_URLs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_json = TCT.format_query_json(input_node1_list,  # a list of identifiers for input node1\n",
    "                                   input_node2_list,  # it can be empty list if only want to query node1\n",
    "                                   input_node1_category,  # a list of categories of input node1\n",
    "                                   input_node2_category,  # a list of categories of input node2\n",
    "                                   sele_predicates) # a list of pre"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'Automat-ehr-clinical-connections-kp(Trapi v1.5.0)' generated an exception: argument of type 'NoneType' is not iterable\n",
      "Microbiome KP - TRAPI 1.5.0: Success!\n",
      "'Automat-ehr-may-treat-kp(Trapi v1.5.0)' generated an exception: argument of type 'NoneType' is not iterable\n",
      "'imProving Agent for TRAPI 1.5' generated an exception: argument of type 'NoneType' is not iterable\n",
      "'SPOKE KP for TRAPI 1.5' generated an exception: argument of type 'NoneType' is not iterable\n",
      "'Automat-icees-kg(Trapi v1.5.0)' generated an exception: argument of type 'NoneType' is not iterable\n",
      "'Automat-monarchinitiative(Trapi v1.5.0)' generated an exception: argument of type 'NoneType' is not iterable\n",
      "'MolePro' generated an exception: argument of type 'NoneType' is not iterable\n",
      "'Multiomics KP - TRAPI 1.5.0' generated an exception: argument of type 'NoneType' is not iterable\n",
      "'Text Mined Cooccurrence API' generated an exception: argument of type 'NoneType' is not iterable\n",
      "Automat-genome-alliance(Trapi v1.5.0): Success!\n",
      "'Connections Hypothesis Provider API' generated an exception: 'NoneType' object has no attribute 'get'\n",
      "Automat-cam-kp(Trapi v1.5.0): Success!\n",
      "CATRAX Pharmacogenomics KP - TRAPI 1.5.0: Success!\n",
      "CATRAX BigGIM DrugResponse Performance Phase KP - TRAPI 1.5.0: Success!\n",
      "Automat-hetionet(Trapi v1.5.0): Success!\n",
      "Automat-pharos(Trapi v1.5.0): Success!\n",
      "RTX KG2 - TRAPI 1.5.0: Success!\n",
      "Automat-robokop(Trapi v1.5.0): Success!\n",
      "Service Provider TRAPI: Success!\n",
      "BioThings Explorer (BTE) TRAPI: Success!\n"
     ]
    }
   ],
   "source": [
    "# Step 5: Query Translator APIs and parse results\n",
    "\n",
    "result = translator_query.parallel_api_query(query_json=query_json, \n",
    "                             select_APIs= sele_APIs, \n",
    "                             APInames=APInames,\n",
    "                             API_predicates=API_predicates,\n",
    "                             max_workers=len(sele_APIs))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'NCBIGene:596': TranslatorNode(curie='UniProtKB:A0A4X1SN03', label='A0A4X1SN03_PIG Zinc finger protein 596 (trembl)', types=['biolink:Protein', 'biolink:GeneProductMixin', 'biolink:Polypeptide', 'biolink:ChemicalEntityOrGeneOrGeneProduct', 'biolink:ChemicalEntityOrProteinOrPolypeptide', 'biolink:BiologicalEntity', 'biolink:ThingWithTaxon', 'biolink:NamedThing', 'biolink:Entity', 'biolink:GeneOrGeneProduct', 'biolink:MacromolecularMachineMixin'], synonyms=None, curie_synonyms=None), 'NCBIGene:4869': TranslatorNode(curie='PUBCHEM.COMPOUND:676542', label='Cl-4869 peak 2', types=['biolink:SmallMolecule', 'biolink:MolecularEntity', 'biolink:ChemicalEntity', 'biolink:PhysicalEssence', 'biolink:ChemicalOrDrugOrTreatment', 'biolink:ChemicalEntityOrGeneOrGeneProduct', 'biolink:ChemicalEntityOrProteinOrPolypeptide', 'biolink:NamedThing', 'biolink:Entity', 'biolink:PhysicalEssenceOrOccurrent'], synonyms=None, curie_synonyms=None), 'NCBIGene:4893': TranslatorNode(curie='MESH:C568585', label='S-4893 compound', types=['biolink:ChemicalEntity', 'biolink:PhysicalEssence', 'biolink:ChemicalOrDrugOrTreatment', 'biolink:ChemicalEntityOrGeneOrGeneProduct', 'biolink:ChemicalEntityOrProteinOrPolypeptide', 'biolink:NamedThing', 'biolink:Entity', 'biolink:PhysicalEssenceOrOccurrent'], synonyms=None, curie_synonyms=None), 'NCBIGene:2322': TranslatorNode(curie='NCBIGene:100313282', label='MIR2322', types=['biolink:Gene', 'biolink:GeneOrGeneProduct', 'biolink:GenomicEntity', 'biolink:ChemicalEntityOrGeneOrGeneProduct', 'biolink:PhysicalEssence', 'biolink:OntologyClass', 'biolink:BiologicalEntity', 'biolink:ThingWithTaxon', 'biolink:NamedThing', 'biolink:Entity', 'biolink:PhysicalEssenceOrOccurrent', 'biolink:MacromolecularMachineMixin'], synonyms=None, curie_synonyms=None)}\n",
      "         Subject         Object                          Predicate\n",
      "0  NCBIGene:2322  NCBIGene:4893            biolink:associated_with\n",
      "1  NCBIGene:4893  NCBIGene:2322            biolink:associated_with\n",
      "2  NCBIGene:2322  NCBIGene:2322                  biolink:regulates\n",
      "3  NCBIGene:2322  NCBIGene:2322  biolink:physically_interacts_with\n",
      "4   NCBIGene:596   NCBIGene:596  biolink:physically_interacts_with\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "47073cd47e494b05b9875a0906f3dffb",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "CytoscapeWidget(cytoscape_layout={'name': 'cose', 'nodeSpacing': 80, 'edgeLengthVal': 50}, cytoscape_style=[{'…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# select the recored in the result which is a dictionary if the subject and objects are both in input_node1_list\n",
    "result_filtered = {k: v for k, v in result.items() if isinstance(v, dict) and\n",
    "                   v.get('subject') in input_node1_list and\n",
    "                   v.get('object') in input_node1_list}\n",
    "\n",
    "len(result_filtered)\n",
    "result_df =visualize_interaction_network(result_filtered)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "3.12.1",
   "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.12.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
