{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Hawksight-AI/semantica/blob/main/cookbook/use_cases/biomedical/02_Genomic_Variant_Analysis.ipynb)\n",
    "\n",
    "# Genomic Variant Analysis - Graph Analytics & Pathway Analysis\n",
    "\n",
    "## Overview\n",
    "\n",
    "This notebook demonstrates **genomic variant analysis** using Semantica's modular architecture with focus on **graph analytics**, **pathway analysis**, and **temporal knowledge graphs**. The pipeline analyzes genomic data to extract variant entities, build temporal genomic knowledge graphs, and analyze disease associations through reasoning.\n",
    "\n",
    "### Key Features\n",
    "\n",
    "- **Graph Analytics Focus**: Emphasizes graph reasoning, centrality measures, and pathway analysis\n",
    "- **Temporal Analysis**: Builds temporal genomic knowledge graphs to track variant evolution\n",
    "- **Disease Association**: Analyzes relationships between variants, genes, and diseases\n",
    "- **Pathway Analysis**: Uses graph traversal to identify biological pathways\n",
    "- **Impact Prediction**: Predicts variant impact using graph-based reasoning\n",
    "\n",
    "### What You'll Learn\n",
    "\n",
    "- How to use Semantica modules directly for genomic analysis\n",
    "- How to ingest genomic data from multiple sources\n",
    "- How to extract variant, gene, and disease entities\n",
    "- How to build temporal knowledge graphs\n",
    "- How to perform graph analytics (centrality, communities)\n",
    "- How to use temporal queries for variant evolution\n",
    "- How to analyze pathways using reasoning\n",
    "- How to visualize and export genomic knowledge graphs\n",
    "\n",
    "### Pipeline Flow\n",
    "\n",
    "```mermaid\n",
    "graph LR\n",
    "    A[Data Ingestion] --> B[Text Processing]\n",
    "    B --> C[Entity Extraction]\n",
    "    C --> D[Relationship Extraction]\n",
    "    D --> E[Deduplication]\n",
    "    E --> F[Temporal KG]\n",
    "    F --> G[Graph Analytics]\n",
    "    F --> H[Temporal Queries]\n",
    "    G --> I[Pathway Analysis]\n",
    "    H --> I\n",
    "    I --> J[Disease Associations]\n",
    "    J --> K[Visualization]\n",
    "```\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Installation\n",
    "\n",
    "Install Semantica and required dependencies:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install -qU semantica networkx matplotlib plotly pandas groq sentence-transformers\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configuration & Setup\n",
    "\n",
    "Set up environment variables and configuration constants.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"GROQ_API_KEY\"] = os.getenv(\"GROQ_API_KEY\", \"\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "CHUNK_SIZE = 1000\n",
    "CHUNK_OVERLAP = 200\n",
    "TEMPORAL_GRANULARITY = \"day\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ingesting Genomic Data from Multiple Sources\n",
    "\n",
    "Ingest data from comprehensive genomic sources including PubMed RSS feeds, preprint servers, and journal feeds.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.ingest import FeedIngestor, FileIngestor\n",
    "import os\n",
    "from contextlib import redirect_stderr\n",
    "from io import StringIO\n",
    "\n",
    "os.makedirs(\"data\", exist_ok=True)\n",
    "\n",
    "feed_sources = [\n",
    "    # PubMed RSS Feeds (simplified, working format)\n",
    "    (\"PubMed - Genetics\", \"https://pubmed.ncbi.nlm.nih.gov/rss/search/1?term=genetics&limit=10\"),\n",
    "    (\"PubMed - Genomics\", \"https://pubmed.ncbi.nlm.nih.gov/rss/search/1?term=genomics&limit=10\"),\n",
    "    (\"PubMed - Variant Analysis\", \"https://pubmed.ncbi.nlm.nih.gov/rss/search/1?term=variant+analysis&limit=10\"),\n",
    "    (\"PubMed - GWAS\", \"https://pubmed.ncbi.nlm.nih.gov/rss/search/1?term=GWAS&limit=10\"),\n",
    "    (\"PubMed - Genomic Medicine\", \"https://pubmed.ncbi.nlm.nih.gov/rss/search/1?term=genomic+medicine&limit=10\"),\n",
    "    (\"PubMed - Precision Medicine\", \"https://pubmed.ncbi.nlm.nih.gov/rss/search/1?term=precision+medicine&limit=10\"),\n",
    "    (\"PubMed - Pharmacogenomics\", \"https://pubmed.ncbi.nlm.nih.gov/rss/search/1?term=pharmacogenomics&limit=10\"),\n",
    "    \n",
    "    # Nature Feeds (working format)\n",
    "    (\"Nature Genetics\", \"https://www.nature.com/subjects/genetics.rss\"),\n",
    "    (\"Nature - Genomics\", \"https://www.nature.com/subjects/genomics.rss\"),\n",
    "    \n",
    "    # PLOS Journals (working Atom feeds)\n",
    "    (\"PLOS Genetics\", \"https://journals.plos.org/plosgenetics/feed/atom\"),\n",
    "    (\"PLOS ONE - Genetics\", \"https://journals.plos.org/plosone/feed/atom\"),\n",
    "    \n",
    "    # Other working feeds\n",
    "    (\"Genome Research\", \"https://genome.cshlp.org/rss/current.xml\"),\n",
    "]\n",
    "\n",
    "feed_ingestor = FeedIngestor()\n",
    "all_documents = []\n",
    "\n",
    "print(f\"Ingesting from {len(feed_sources)} feed sources...\")\n",
    "for i, (feed_name, feed_url) in enumerate(feed_sources, 1):\n",
    "    try:\n",
    "        with redirect_stderr(StringIO()):\n",
    "            feed_data = feed_ingestor.ingest_feed(feed_url, validate=False)\n",
    "        \n",
    "        feed_count = 0\n",
    "        for item in feed_data.items:\n",
    "            if not item.content:\n",
    "                item.content = item.description or item.title or \"\"\n",
    "            if item.content:\n",
    "                if not hasattr(item, 'metadata'):\n",
    "                    item.metadata = {}\n",
    "                item.metadata['source'] = feed_name\n",
    "                all_documents.append(item)\n",
    "                feed_count += 1\n",
    "        \n",
    "        if feed_count > 0:\n",
    "            print(f\"  [{i}/{len(feed_sources)}] {feed_name}: {feed_count} documents\")\n",
    "    except Exception as e:\n",
    "        print(f\"  [{i}/{len(feed_sources)}] {feed_name}: Failed\")\n",
    "        continue\n",
    "\n",
    "# Always include fallback variant data for demonstration\n",
    "variant_data = \"\"\"\n",
    "Variant rs699 is located in the AGT gene and associated with hypertension.\n",
    "Variant rs7412 in APOE gene is linked to Alzheimer's disease risk.\n",
    "BRCA1 variant c.5266dupC increases breast cancer susceptibility.\n",
    "CFTR variant F508del causes cystic fibrosis.\n",
    "Variant rs1800566 in NAT2 gene affects drug metabolism.\n",
    "Variant rs1042713 in ADRB2 gene is associated with asthma response.\n",
    "TP53 variant R273H is linked to multiple cancer types.\n",
    "Variant rs1799853 in CYP2C9 gene affects warfarin metabolism.\n",
    "Variant rs1057910 in CYP2C9 affects phenytoin metabolism.\n",
    "Variant rs9923231 in VKORC1 gene influences warfarin dosing.\n",
    "\"\"\"\n",
    "\n",
    "with open(\"data/variants.txt\", \"w\") as f:\n",
    "    f.write(variant_data)\n",
    "\n",
    "file_ingestor = FileIngestor()\n",
    "fallback_docs = file_ingestor.ingest(\"data/variants.txt\")\n",
    "all_documents.extend(fallback_docs)\n",
    "\n",
    "documents = all_documents\n",
    "print(f\"\\nTotal ingested: {len(documents)} documents\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Normalizing and Chunking Genomic Documents\n",
    "\n",
    "Clean and normalize text, then split into chunks using entity-aware chunking to preserve variant/gene entity boundaries.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.normalize import TextNormalizer\n",
    "from semantica.split import TextSplitter\n",
    "\n",
    "normalizer = TextNormalizer()\n",
    "splitter = TextSplitter(\n",
    "    method=\"entity_aware\",\n",
    "    ner_method=\"spacy\",\n",
    "    chunk_size=CHUNK_SIZE,\n",
    "    chunk_overlap=CHUNK_OVERLAP\n",
    ")\n",
    "\n",
    "print(f\"Normalizing {len(documents)} documents...\")\n",
    "normalized_documents = []\n",
    "for i, doc in enumerate(documents, 1):\n",
    "    normalized_text = normalizer.normalize(\n",
    "        doc.content if hasattr(doc, 'content') else str(doc),\n",
    "        clean_html=True,\n",
    "        normalize_entities=True,\n",
    "        remove_extra_whitespace=True,\n",
    "        lowercase=False\n",
    "    )\n",
    "    normalized_documents.append(normalized_text)\n",
    "    if i % 50 == 0 or i == len(documents):\n",
    "        print(f\"  Normalized {i}/{len(documents)} documents...\")\n",
    "\n",
    "print(f\"Chunking {len(normalized_documents)} documents...\")\n",
    "chunked_documents = []\n",
    "for i, doc_text in enumerate(normalized_documents, 1):\n",
    "    try:\n",
    "        with redirect_stderr(StringIO()):\n",
    "            chunks = splitter.split(doc_text)\n",
    "        chunked_documents.extend(chunks)\n",
    "    except Exception:\n",
    "        simple_splitter = TextSplitter(method=\"recursive\", chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP)\n",
    "        chunks = simple_splitter.split(doc_text)\n",
    "        chunked_documents.extend(chunks)\n",
    "    if i % 50 == 0 or i == len(normalized_documents):\n",
    "        print(f\"  Chunked {i}/{len(normalized_documents)} documents ({len(chunked_documents)} chunks so far)\")\n",
    "\n",
    "print(f\"Created {len(chunked_documents)} chunks from {len(normalized_documents)} documents\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.semantic_extract import NERExtractor\n",
    "\n",
    "# Using spaCy ML method (similar to Drug Discovery Pipeline)\n",
    "entity_extractor = NERExtractor(method=\"ml\", model=\"en_core_web_sm\")\n",
    "\n",
    "all_entities = []\n",
    "print(f\"Extracting entities from {len(chunked_documents)} chunks...\")\n",
    "\n",
    "for i, chunk in enumerate(chunked_documents, 1):\n",
    "    chunk_text = chunk.text if hasattr(chunk, 'text') else str(chunk)\n",
    "    try:\n",
    "        entities = entity_extractor.extract_entities(chunk_text)\n",
    "        all_entities.extend(entities)\n",
    "    except Exception:\n",
    "        continue\n",
    "    \n",
    "    if i % 20 == 0 or i == len(chunked_documents):\n",
    "        remaining = len(chunked_documents) - i\n",
    "        print(f\"  Processed {i}/{len(chunked_documents)} chunks ({len(all_entities)} entities found, {remaining} remaining)\")\n",
    "\n",
    "# Filter entities - spaCy returns standard types, map to genomic categories\n",
    "# Look for variant patterns (rs numbers, c. notation, etc.)\n",
    "variants = [\n",
    "    e for e in all_entities \n",
    "    if (e.text.startswith(\"rs\") or \n",
    "        \"c.\" in e.text.lower() or \n",
    "        \"variant\" in e.text.lower() or\n",
    "        e.label == \"PRODUCT\" and any(kw in e.text.lower() for kw in [\"rs\", \"variant\", \"mutation\"]))\n",
    "]\n",
    "\n",
    "# Look for gene patterns (gene names, protein names)\n",
    "genes = [\n",
    "    e for e in all_entities \n",
    "    if (e.label == \"ORG\" or \n",
    "        e.label == \"PRODUCT\" or\n",
    "        any(kw in e.text.lower() for kw in [\"gene\", \"protein\", \"enzyme\", \"receptor\", \"kinase\"]))\n",
    "]\n",
    "\n",
    "# Look for disease patterns\n",
    "diseases = [\n",
    "    e for e in all_entities \n",
    "    if (e.label == \"ORG\" or\n",
    "        any(kw in e.text.lower() for kw in [\"disease\", \"syndrome\", \"disorder\", \"cancer\", \"hypertension\", \"alzheimer\"]))\n",
    "]\n",
    "\n",
    "print(f\"Extracted {len(variants)} variants, {len(genes)} genes, {len(diseases)} diseases\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extracting Genomic Relationships\n",
    "\n",
    "Extract relationships between variants, genes, and diseases to understand genomic associations.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.semantic_extract import RelationExtractor\n",
    "\n",
    "# Using spaCy dependency parsing (similar to Drug Discovery Pipeline)\n",
    "relation_extractor = RelationExtractor(method=\"dependency\", model=\"en_core_web_sm\")\n",
    "\n",
    "all_relationships = []\n",
    "print(f\"Extracting relationships from {len(chunked_documents)} chunks...\")\n",
    "\n",
    "for i, chunk in enumerate(chunked_documents, 1):\n",
    "    chunk_text = chunk.text if hasattr(chunk, 'text') else str(chunk)\n",
    "    try:\n",
    "        relationships = relation_extractor.extract_relations(\n",
    "            chunk_text,\n",
    "            entities=all_entities,\n",
    "            relation_types=[\"associated_with\", \"located_in\", \"causes\", \"increases_risk\", \"affects\", \"linked_to\"]\n",
    "        )\n",
    "        all_relationships.extend(relationships)\n",
    "    except Exception:\n",
    "        continue\n",
    "    \n",
    "    if i % 20 == 0 or i == len(chunked_documents):\n",
    "        print(f\"  Processed {i}/{len(chunked_documents)} chunks ({len(all_relationships)} relationships found)\")\n",
    "\n",
    "print(f\"Extracted {len(all_relationships)} relationships\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Building Temporal Genomic Knowledge Graph\n",
    "\n",
    "Construct a temporal knowledge graph from extracted entities and relationships to enable time-aware analysis and variant evolution tracking.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conflict Detection and Resolution\n",
    "\n",
    "Detect and resolve conflicts in genomic variant data from multiple research sources.\n",
    "\n",
    "- **Detection Method**: Entity and relationship conflict detection identifies discrepancies in variant-gene-disease associations across sources\n",
    "- **Resolution Strategy**: Credibility-weighted resolution prioritizes higher-credibility sources (e.g., Nature Genetics over preprints)\n",
    "- **Use Case**: Handles conflicting information when multiple sources report different variant associations, disease risks, or gene locations\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.conflicts import ConflictDetector, ConflictResolver\n",
    "\n",
    "# Initialize with best strategies for genomic analysis\n",
    "detector = ConflictDetector()\n",
    "resolver = ConflictResolver(default_strategy=\"credibility_weighted\")\n",
    "\n",
    "# Convert entities to format expected by detector\n",
    "entities = [\n",
    "    {\n",
    "        \"id\": ent.text if hasattr(ent, 'text') else str(ent),\n",
    "        \"name\": ent.text if hasattr(ent, 'text') else str(ent),\n",
    "        \"type\": ent.label if hasattr(ent, 'label') else \"ENTITY\",\n",
    "        \"confidence\": getattr(ent, 'confidence', 1.0),\n",
    "        \"source\": ent.metadata.get(\"source\", \"unknown\") if hasattr(ent, 'metadata') and ent.metadata else \"unknown\"\n",
    "    }\n",
    "    for ent in all_entities if hasattr(ent, 'text') or hasattr(ent, 'label')\n",
    "]\n",
    "\n",
    "# Convert relationships to format expected by detector\n",
    "relationships = [\n",
    "    {\n",
    "        \"id\": f\"{rel.subject.text}_{rel.object.text}_{rel.predicate}\" if hasattr(rel, 'subject') else f\"{i}\",\n",
    "        \"source_id\": rel.subject.text if hasattr(rel, 'subject') else str(rel.get(\"source\", \"\")),\n",
    "        \"target_id\": rel.object.text if hasattr(rel, 'object') else str(rel.get(\"target\", \"\")),\n",
    "        \"type\": rel.predicate if hasattr(rel, 'predicate') else rel.get(\"type\", \"related_to\"),\n",
    "        \"confidence\": getattr(rel, 'confidence', 1.0),\n",
    "        \"properties\": rel.metadata if hasattr(rel, 'metadata') else {},\n",
    "        \"source\": rel.metadata.get(\"source\", \"unknown\") if hasattr(rel, 'metadata') and rel.metadata else \"unknown\"\n",
    "    }\n",
    "    for i, rel in enumerate(all_relationships) if hasattr(rel, 'subject') or isinstance(rel, dict)\n",
    "]\n",
    "\n",
    "# Detect both entity and relationship conflicts\n",
    "print(f\"Detecting conflicts in {len(entities)} entities, {len(relationships)} relationships...\")\n",
    "\n",
    "# Detect entity conflicts\n",
    "entity_conflicts = detector.detect_conflicts(entities)\n",
    "print(f\"Detected {len(entity_conflicts)} entity conflicts\")\n",
    "\n",
    "# Detect relationship conflicts\n",
    "relationship_conflicts = detector.detect_relationship_conflicts(relationships)\n",
    "print(f\"Detected {len(relationship_conflicts)} relationship conflicts\")\n",
    "\n",
    "# Resolve entity conflicts\n",
    "if entity_conflicts:\n",
    "    resolver.resolve_conflicts(entity_conflicts, strategy=\"credibility_weighted\")\n",
    "    print(f\"Resolved {len(entity_conflicts)} entity conflicts\")\n",
    "\n",
    "# Resolve relationship conflicts\n",
    "if relationship_conflicts:\n",
    "    resolver.resolve_conflicts(relationship_conflicts, strategy=\"credibility_weighted\")\n",
    "    print(f\"Resolved {len(relationship_conflicts)} relationship conflicts\")\n",
    "\n",
    "# GraphBuilder will use resolve_conflicts=True to apply resolutions automatically\n",
    "if entity_conflicts or relationship_conflicts:\n",
    "    print(\"Conflicts resolved. GraphBuilder will use cleaned data.\")\n",
    "else:\n",
    "    print(\"No conflicts detected. Data is clean.\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import GraphBuilder\n",
    "\n",
    "# Conflicts already detected and resolved in previous cell\n",
    "# Enable temporal features for genomic variant tracking\n",
    "graph_builder = GraphBuilder(\n",
    "    resolve_conflicts=False,  # Conflicts already handled\n",
    "    enable_temporal=True,\n",
    "    temporal_granularity=TEMPORAL_GRANULARITY\n",
    ")\n",
    "\n",
    "print(f\"Building temporal knowledge graph from {len(all_entities)} entities, {len(all_relationships)} relationships...\")\n",
    "kg = graph_builder.build({\n",
    "    \"entities\": all_entities,\n",
    "    \"relationships\": all_relationships\n",
    "})\n",
    "\n",
    "entities_count = len(kg.get('entities', []))\n",
    "relationships_count = len(kg.get('relationships', []))\n",
    "print(f\"Graph: {entities_count} entities, {relationships_count} relationships\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Analyzing Graph Structure\n",
    "\n",
    "Perform comprehensive graph analytics including centrality measures, community detection, and connectivity analysis.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import GraphAnalyzer, CentralityCalculator, CommunityDetector\n",
    "\n",
    "graph_analyzer = GraphAnalyzer()\n",
    "centrality_calc = CentralityCalculator()\n",
    "community_detector = CommunityDetector()\n",
    "\n",
    "analysis = graph_analyzer.analyze_graph(kg)\n",
    "\n",
    "degree_centrality = centrality_calc.calculate_degree_centrality(kg)\n",
    "betweenness_centrality = centrality_calc.calculate_betweenness_centrality(kg)\n",
    "closeness_centrality = centrality_calc.calculate_closeness_centrality(kg)\n",
    "\n",
    "communities = community_detector.detect_communities(kg, method=\"louvain\")\n",
    "connectivity = graph_analyzer.analyze_connectivity(kg)\n",
    "\n",
    "print(f\"Graph analytics:\")\n",
    "print(f\"  - Communities: {len(communities)}\")\n",
    "print(f\"  - Connected components: {len(connectivity.get('components', []))}\")\n",
    "print(f\"  - Graph density: {analysis.get('density', 0):.3f}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Temporal Graph Queries\n",
    "\n",
    "Query the temporal knowledge graph at specific time points, analyze temporal evolution, and detect temporal patterns.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import TemporalGraphQuery\n",
    "\n",
    "temporal_query = TemporalGraphQuery(\n",
    "    enable_temporal_reasoning=True,\n",
    "    temporal_granularity=TEMPORAL_GRANULARITY\n",
    ")\n",
    "\n",
    "# Query variants at specific time point\n",
    "query_results = temporal_query.query_at_time(\n",
    "    kg,\n",
    "    query=\"Variant\",\n",
    "    at_time=\"2024-01-01\"\n",
    ")\n",
    "\n",
    "# Analyze graph evolution\n",
    "evolution = temporal_query.analyze_evolution(kg)\n",
    "\n",
    "# Detect temporal patterns\n",
    "pattern_results = temporal_query.query_temporal_pattern(\n",
    "    kg,\n",
    "    pattern=\"sequence\"\n",
    ")\n",
    "\n",
    "print(f\"Temporal query: {query_results.get('num_relationships', 0)} relationships valid at query time\")\n",
    "print(f\"Evolution analysis: {evolution.get('num_relationships', 0)} relationships tracked\")\n",
    "print(f\"Temporal patterns detected: {pattern_results.get('num_patterns', 0)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pathway Analysis & Reasoning\n",
    "\n",
    "Use graph reasoning to find pathways between variants and diseases, and infer biological pathways through logical reasoning.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.reasoning import Reasoner\n",
    "from semantica.kg import GraphAnalyzer\n",
    "\n",
    "reasoner = Reasoner()\n",
    "graph_analyzer = GraphAnalyzer()\n",
    "\n",
    "# Find entities by type\n",
    "variants = [e for e in kg.get('entities', []) if e.get('type') == 'Variant']\n",
    "diseases = [e for e in kg.get('entities', []) if e.get('type') == 'Disease']\n",
    "\n",
    "print(f\"Found {len(variants)} variants and {len(diseases)} diseases\")\n",
    "\n",
    "# Find pathways\n",
    "pathways = []\n",
    "for variant in variants[:5]:\n",
    "    variant_id = variant.get('id') or variant.get('name')\n",
    "    for disease in diseases[:3]:\n",
    "        disease_id = disease.get('id') or disease.get('name')\n",
    "        path = graph_analyzer.connectivity_analyzer.calculate_shortest_paths(\n",
    "            kg, source=variant_id, target=disease_id\n",
    "        )\n",
    "        if path.get('exists'):\n",
    "            pathways.append({\n",
    "                'variant': variant_id,\n",
    "                'disease': disease_id,\n",
    "                'distance': path.get('distance', -1)\n",
    "            })\n",
    "\n",
    "# Add rule and infer facts\n",
    "reasoner.add_rule(\"IF Variant associated_with Gene AND Gene causes Disease THEN Variant increases_risk Disease\")\n",
    "inferred_facts = reasoner.infer_facts(kg)\n",
    "\n",
    "print(f\"Pathway analysis: {len(pathways)} variant-disease pathways found\")\n",
    "print(f\"Inferred facts: {len(inferred_facts)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Analyzing Disease Associations\n",
    "\n",
    "Use graph traversal to find variant-disease associations and calculate association scores.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.kg import GraphAnalyzer\n",
    "\n",
    "graph_analyzer = GraphAnalyzer()\n",
    "\n",
    "# Find entities by type\n",
    "variants = [e for e in kg.get('entities', []) if e.get('type') == 'Variant']\n",
    "diseases = [e for e in kg.get('entities', []) if e.get('type') == 'Disease']\n",
    "\n",
    "# Find disease associations\n",
    "disease_associations = []\n",
    "for variant in variants[:10]:\n",
    "    variant_id = variant.get('name') or variant.get('id')\n",
    "    if not variant_id:\n",
    "        continue\n",
    "    for disease in diseases[:5]:\n",
    "        disease_id = disease.get('name') or disease.get('id')\n",
    "        if not disease_id:\n",
    "            continue\n",
    "        path = graph_analyzer.connectivity_analyzer.calculate_shortest_paths(\n",
    "            kg, source=variant_id, target=disease_id\n",
    "        )\n",
    "        if path.get('exists') and path.get('distance', -1) <= 2:\n",
    "            disease_associations.append({\n",
    "                'variant': variant_id,\n",
    "                'disease': disease_id,\n",
    "                'path_length': path.get('distance', -1),\n",
    "                'confidence': variant.get('confidence', 1.0)\n",
    "            })\n",
    "\n",
    "disease_associations.sort(key=lambda x: x['confidence'], reverse=True)\n",
    "\n",
    "print(f\"Top disease associations:\")\n",
    "for i, assoc in enumerate(disease_associations[:5], 1):\n",
    "    print(f\"{i}. {assoc['variant']} -> {assoc['disease']} (path length: {assoc['path_length']}, confidence: {assoc['confidence']:.3f})\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualizing the Temporal Knowledge Graph\n",
    "\n",
    "Generate an interactive visualization of the temporal genomic knowledge graph.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.visualization import TemporalVisualizer\n",
    "\n",
    "# Visualize temporal dashboard\n",
    "temporal_viz = TemporalVisualizer()\n",
    "fig = temporal_viz.visualize_temporal_dashboard(\n",
    "    kg,\n",
    "    output=\"interactive\"\n",
    ")\n",
    "\n",
    "# Display the figure\n",
    "fig.show() if fig else None\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exporting Results\n",
    "\n",
    "Export the temporal knowledge graph to various formats for further analysis or integration with other tools.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.export import GraphExporter\n",
    "\n",
    "exporter = GraphExporter()\n",
    "exporter.export(kg, output_path=\"genomic_variant_kg.json\", format=\"json\")\n",
    "exporter.export(kg, output_path=\"genomic_variant_kg.graphml\", format=\"graphml\")\n",
    "\n",
    "print(\"Exported knowledge graph to JSON and GraphML formats\")\n"
   ]
  }
 ],
 "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.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
