{
 "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/intelligence/03_Law_Enforcement_Forensics.ipynb)\n",
    "\n",
    "# Law Enforcement and Forensics Analysis with Semantica\n",
    "\n",
    "## Overview\n",
    "\n",
    "This notebook demonstrates a complete forensic analysis pipeline using **Semantica as the core framework** with agent-based workflows for processing case files, evidence logs, witness statements, and forensic reports. The pipeline builds temporal knowledge graphs, correlates evidence across cases, and generates comprehensive forensic analysis reports.\n",
    "\n",
    "\n",
    "**Documentation**: [API Reference](https://semantica.readthedocs.io/use-cases/)\n",
    "\n",
    "### Why Semantica?\n",
    "\n",
    "Semantica provides a complete framework for forensic analysis:\n",
    "\n",
    "- **Multi-Source Evidence Processing**: Process case files, evidence logs, witness statements, forensic reports, and crime scene data\n",
    "- **Agent-Based Workflows**: Autonomous agents with persistent memory for coordinated evidence analysis\n",
    "- **Temporal Knowledge Graphs**: Build time-aware knowledge graphs for case timelines and evidence correlation\n",
    "- **Cross-Case Correlation**: Identify connections and patterns across multiple cases\n",
    "- **Graph Analytics**: Analyze evidence networks and case relationships\n",
    "- **GraphRAG**: Semantic search across case files with context-aware evidence retrieval\n",
    "- **Forensic Reporting**: Generate comprehensive forensic analysis reports with evidence chains\n",
    "\n",
    "### Key Features\n",
    "\n",
    "- Process forensic evidence from multiple sources\n",
    "- Extract entities (persons, locations, evidence, events) and relationships\n",
    "- Build temporal knowledge graphs for case timelines\n",
    "- Correlate evidence across multiple cases\n",
    "- Agent-based analysis with persistent memory\n",
    "- Graph analytics for evidence network analysis\n",
    "- GraphRAG for semantic search across case files\n",
    "- Generate forensic analysis reports with evidence chains\n",
    "\n",
    "### Semantica Modules Used (25+)\n",
    "\n",
    "- **Ingest**: FileIngestor, WebIngestor, FeedIngestor, StreamIngestor, DBIngestor, RepoIngestor, EmailIngestor, MCPIngestor (case files, evidence databases)\n",
    "- **Parse**: DocumentParser, StructuredDataParser, JSONParser, CSVParser\n",
    "- **Normalize**: TextNormalizer, DataNormalizer\n",
    "- **Semantic Extract**: NERExtractor, RelationExtractor, TripleExtractor, EventDetector\n",
    "- **KG**: GraphBuilder, TemporalGraphQuery, GraphAnalyzer, ConnectivityAnalyzer\n",
    "- **Graph Analytics**: Community detection, centrality measures, path finding\n",
    "- **Embeddings**: EmbeddingGenerator, TextEmbedder\n",
    "- **Vector Store**: VectorStore, HybridSearch, MetadataFilter\n",
    "- **Context**: AgentMemory, ContextRetriever, ContextGraphBuilder\n",
    "- **Pipeline**: PipelineBuilder, ExecutionEngine, ParallelismManager\n",
    "- **Reasoning**: InferenceEngine, RuleManager, ExplanationGenerator\n",
    "- **Export**: ReportGenerator, JSONExporter\n",
    "- **Visualization**: KGVisualizer, AnalyticsVisualizer, TemporalVisualizer\n",
    "- **Deduplication**: DuplicateDetector, EntityMerger\n",
    "\n",
    "### Pipeline Overview\n",
    "\n",
    "**Case Files → Parse → Extract Evidence Entities/Relationships → Build Temporal Case KG → Graph Analytics → GraphRAG → Agent Analysis → Cross-Case Correlation → Generate Forensic Report → Visualize**\n",
    "\n",
    "## Installation\n",
    "\n",
    "Install Semantica from PyPI:\n",
    "\n",
    "```bash\n",
    "pip install semantica\n",
    "# Or with all optional dependencies:\n",
    "pip install semantica[all]\n",
    "```\n",
    "\n",
    "---\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1: Setup and Import Semantica Modules\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import all Semantica modules for forensic analysis\n",
    "from semantica.ingest import FileIngestor, DBIngestor\n",
    "from semantica.parse import DocumentParser, StructuredDataParser, JSONParser, CSVParser\n",
    "from semantica.normalize import TextNormalizer, DataNormalizer\n",
    "from semantica.semantic_extract import NERExtractor, RelationExtractor, TripleExtractor, EventDetector\n",
    "from semantica.kg import GraphBuilder, TemporalGraphQuery, GraphAnalyzer, ConnectivityAnalyzer\n",
    "from semantica.embeddings import EmbeddingGenerator, TextEmbedder\n",
    "from semantica.vector_store import VectorStore, HybridSearch, MetadataFilter\n",
    "from semantica.context import AgentMemory, ContextRetriever, ContextGraphBuilder\n",
    "from semantica.pipeline import PipelineBuilder, ExecutionEngine, ParallelismManager\n",
    "from semantica.reasoning import InferenceEngine, RuleManager, ExplanationGenerator\n",
    "from semantica.export import ReportGenerator, JSONExporter\n",
    "from semantica.visualization import KGVisualizer, AnalyticsVisualizer, TemporalVisualizer\n",
    "from semantica.deduplication import DuplicateDetector, EntityMerger\n",
    "\n",
    "import tempfile\n",
    "import os\n",
    "import json\n",
    "from datetime import datetime, timedelta\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2: Initialize Agent Memory and Setup Agents\n",
    "\n",
    "Set up AgentMemory for persistent context and initialize specialized forensic analysis agents.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize vector store for agent memory\n",
    "vector_store = VectorStore(backend=\"faiss\", dimension=768)\n",
    "\n",
    "# Initialize agent memory for persistent context\n",
    "agent_memory = AgentMemory(\n",
    "    vector_store=vector_store,\n",
    "    retention_policy=\"unlimited\",\n",
    "    max_memory_size=10000\n",
    ")\n",
    "\n",
    "# Initialize Semantica modules\n",
    "file_ingestor = FileIngestor()\n",
    "graph_builder = GraphBuilder()\n",
    "temporal_query = TemporalGraphQuery()\n",
    "graph_analyzer = GraphAnalyzer()\n",
    "inference_engine = InferenceEngine()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 3: Ingest Case Files and Evidence\n",
    "\n",
    "Ingest case files, evidence logs, witness statements, and forensic reports.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create temporary directory for sample data\n",
    "temp_dir = tempfile.mkdtemp()\n",
    "\n",
    "# Sample case files data\n",
    "case_files_data = {\n",
    "    \"cases\": [\n",
    "        {\n",
    "            \"case_id\": \"CF001\",\n",
    "            \"date_opened\": \"2024-01-10\",\n",
    "            \"case_type\": \"Homicide\",\n",
    "            \"location\": \"123 Main Street\",\n",
    "            \"victim\": \"Victim A\",\n",
    "            \"suspects\": [\"Suspect X\", \"Suspect Y\"],\n",
    "            \"status\": \"Active\"\n",
    "        },\n",
    "        {\n",
    "            \"case_id\": \"CF002\",\n",
    "            \"date_opened\": \"2024-02-15\",\n",
    "            \"case_type\": \"Robbery\",\n",
    "            \"location\": \"456 Oak Avenue\",\n",
    "            \"victim\": \"Victim B\",\n",
    "            \"suspects\": [\"Suspect Y\", \"Suspect Z\"],\n",
    "            \"status\": \"Active\"\n",
    "        }\n",
    "    ]\n",
    "}\n",
    "\n",
    "# Sample evidence logs\n",
    "evidence_logs_data = {\n",
    "    \"evidence\": [\n",
    "        {\n",
    "            \"evidence_id\": \"E001\",\n",
    "            \"case_id\": \"CF001\",\n",
    "            \"type\": \"Fingerprint\",\n",
    "            \"location_found\": \"123 Main Street\",\n",
    "            \"date_collected\": \"2024-01-10\",\n",
    "            \"analyzed_by\": \"Forensic Lab A\",\n",
    "            \"results\": \"Match to Suspect X\"\n",
    "        },\n",
    "        {\n",
    "            \"evidence_id\": \"E002\",\n",
    "            \"case_id\": \"CF001\",\n",
    "            \"type\": \"DNA\",\n",
    "            \"location_found\": \"123 Main Street\",\n",
    "            \"date_collected\": \"2024-01-11\",\n",
    "            \"analyzed_by\": \"Forensic Lab B\",\n",
    "            \"results\": \"Match to Suspect X\"\n",
    "        },\n",
    "        {\n",
    "            \"evidence_id\": \"E003\",\n",
    "            \"case_id\": \"CF002\",\n",
    "            \"type\": \"Fingerprint\",\n",
    "            \"location_found\": \"456 Oak Avenue\",\n",
    "            \"date_collected\": \"2024-02-15\",\n",
    "            \"analyzed_by\": \"Forensic Lab A\",\n",
    "            \"results\": \"Match to Suspect Y\"\n",
    "        }\n",
    "    ]\n",
    "}\n",
    "\n",
    "# Sample witness statements\n",
    "witness_statements_data = {\n",
    "    \"statements\": [\n",
    "        {\n",
    "            \"statement_id\": \"WS001\",\n",
    "            \"case_id\": \"CF001\",\n",
    "            \"witness\": \"Witness 1\",\n",
    "            \"date\": \"2024-01-10\",\n",
    "            \"statement\": \"I saw Suspect X and Suspect Y at the scene around 10 PM\"\n",
    "        },\n",
    "        {\n",
    "            \"statement_id\": \"WS002\",\n",
    "            \"case_id\": \"CF002\",\n",
    "            \"witness\": \"Witness 2\",\n",
    "            \"date\": \"2024-02-15\",\n",
    "            \"statement\": \"I observed Suspect Y and Suspect Z leaving the area\"\n",
    "        }\n",
    "    ]\n",
    "}\n",
    "\n",
    "# Save sample data\n",
    "case_files_file = os.path.join(temp_dir, \"case_files.json\")\n",
    "evidence_logs_file = os.path.join(temp_dir, \"evidence_logs.json\")\n",
    "witness_statements_file = os.path.join(temp_dir, \"witness_statements.json\")\n",
    "\n",
    "with open(case_files_file, 'w') as f:\n",
    "    json.dump(case_files_data, f, indent=2)\n",
    "with open(evidence_logs_file, 'w') as f:\n",
    "    json.dump(evidence_logs_data, f, indent=2)\n",
    "with open(witness_statements_file, 'w') as f:\n",
    "    json.dump(witness_statements_data, f, indent=2)\n",
    "\n",
    "# Ingest files\n",
    "case_data = file_ingestor.ingest_file(case_files_file, read_content=True)\n",
    "evidence_data = file_ingestor.ingest_file(evidence_logs_file, read_content=True)\n",
    "witness_data = file_ingestor.ingest_file(witness_statements_file, read_content=True)\n",
    "\n",
    "# Store in agent memory\n",
    "agent_memory.store(\n",
    "    \"Ingested case files, evidence logs, and witness statements\",\n",
    "    metadata={\n",
    "        \"type\": \"data_ingestion\",\n",
    "        \"sources\": [\"case_files\", \"evidence_logs\", \"witness_statements\"],\n",
    "        \"timestamp\": datetime.now().isoformat()\n",
    "    }\n",
    ")\n",
    "\n",
    "print(f\"  - Case files: {len(case_files_data['cases'])}\")\n",
    "print(f\"  - Evidence items: {len(evidence_logs_data['evidence'])}\")\n",
    "print(f\"  - Witness statements: {len(witness_statements_data['statements'])}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize extractors\n",
    "ner_extractor = NERExtractor()\n",
    "relation_extractor = RelationExtractor()\n",
    "event_detector = EventDetector()\n",
    "\n",
    "# Extract forensic entities and relationships\n",
    "forensic_entities = []\n",
    "forensic_relationships = []\n",
    "entity_id_map = {}\n",
    "\n",
    "# Process case files\n",
    "json_parser = JSONParser()\n",
    "parsed_cases = json_parser.parse(case_files_file)\n",
    "parsed_evidence = json_parser.parse(evidence_logs_file)\n",
    "parsed_witnesses = json_parser.parse(witness_statements_file)\n",
    "\n",
    "cases_data = parsed_cases.data if hasattr(parsed_cases, 'data') else parsed_cases\n",
    "evidence_data = parsed_evidence.data if hasattr(parsed_evidence, 'data') else parsed_evidence\n",
    "witnesses_data = parsed_witnesses.data if hasattr(parsed_witnesses, 'data') else parsed_witnesses\n",
    "\n",
    "# Extract entities from cases\n",
    "if isinstance(cases_data, dict):\n",
    "    for case in cases_data.get('cases', []):\n",
    "        case_id = case.get('case_id')\n",
    "        # Add case as entity\n",
    "        forensic_entities.append({\n",
    "            \"id\": case_id,\n",
    "            \"type\": \"Case\",\n",
    "            \"name\": f\"Case {case_id}\",\n",
    "            \"properties\": {\n",
    "                \"case_type\": case.get('case_type'),\n",
    "                \"date_opened\": case.get('date_opened'),\n",
    "                \"status\": case.get('status')\n",
    "            }\n",
    "        })\n",
    "        \n",
    "        # Extract suspects, victims, locations\n",
    "        for suspect in case.get('suspects', []):\n",
    "            if suspect not in entity_id_map:\n",
    "                entity_id = f\"SUSPECT_{len(entity_id_map) + 1}\"\n",
    "                entity_id_map[suspect] = entity_id\n",
    "                forensic_entities.append({\n",
    "                    \"id\": entity_id,\n",
    "                    \"type\": \"Person\",\n",
    "                    \"name\": suspect,\n",
    "                    \"properties\": {\"role\": \"suspect\"}\n",
    "                })\n",
    "            # Create relationship\n",
    "            forensic_relationships.append({\n",
    "                \"source\": case_id,\n",
    "                \"target\": entity_id_map[suspect],\n",
    "                \"type\": \"involves\",\n",
    "                \"properties\": {\"date\": case.get('date_opened')}\n",
    "            })\n",
    "\n",
    "# Extract evidence entities\n",
    "if isinstance(evidence_data, dict):\n",
    "    for evidence in evidence_data.get('evidence', []):\n",
    "        evidence_id = evidence.get('evidence_id')\n",
    "        case_id = evidence.get('case_id')\n",
    "        forensic_entities.append({\n",
    "            \"id\": evidence_id,\n",
    "            \"type\": \"Evidence\",\n",
    "            \"name\": f\"Evidence {evidence_id}\",\n",
    "            \"properties\": {\n",
    "                \"type\": evidence.get('type'),\n",
    "                \"date_collected\": evidence.get('date_collected'),\n",
    "                \"results\": evidence.get('results')\n",
    "            }\n",
    "        })\n",
    "        # Link evidence to case\n",
    "        forensic_relationships.append({\n",
    "            \"source\": case_id,\n",
    "            \"target\": evidence_id,\n",
    "            \"type\": \"has_evidence\",\n",
    "            \"properties\": {\"date\": evidence.get('date_collected')}\n",
    "        })\n",
    "\n",
    "# Build temporal knowledge graph\n",
    "forensic_kg = graph_builder.build(forensic_entities, forensic_relationships)\n",
    "\n",
    "# Store in agent memory\n",
    "agent_memory.store(\n",
    "    f\"Built temporal forensic knowledge graph with {len(forensic_entities)} entities\",\n",
    "    metadata={\n",
    "        \"type\": \"knowledge_graph\",\n",
    "        \"entity_count\": len(forensic_entities),\n",
    "        \"relationship_count\": len(forensic_relationships)\n",
    "    },\n",
    "    entities=forensic_entities,\n",
    "    relationships=forensic_relationships\n",
    ")\n",
    "\n",
    "print(f\"  - Entities: {len(forensic_entities)}\")\n",
    "print(f\"  - Relationships: {len(forensic_relationships)}\")\n",
    "print(f\"  - Cases: {len([e for e in forensic_entities if e.get('type') == 'Case'])}\")\n",
    "print(f\"  - Evidence items: {len([e for e in forensic_entities if e.get('type') == 'Evidence'])}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize pipeline modules\n",
    "pipeline_builder = PipelineBuilder()\n",
    "execution_engine = ExecutionEngine()\n",
    "\n",
    "# Define specialized forensic agents\n",
    "\n",
    "# Agent 1: Evidence Collection Agent\n",
    "def agent_evidence_collection(evidence_data, memory):\n",
    "    \"\"\"Autonomous agent for evidence gathering.\"\"\"\n",
    "    context = memory.retrieve(\"evidence\", max_results=5)\n",
    "    memory.store(\n",
    "        f\"Evidence collection agent processed {len(evidence_data.get('evidence', [])) if isinstance(evidence_data, dict) else 0} evidence items\",\n",
    "        metadata={\"agent\": \"evidence_collection\"}\n",
    "    )\n",
    "    return {\"evidence_processed\": len(evidence_data.get('evidence', [])) if isinstance(evidence_data, dict) else 0}\n",
    "\n",
    "# Agent 2: Timeline Analysis Agent\n",
    "def agent_timeline_analysis(kg, temporal_query, memory):\n",
    "    \"\"\"Agent for building temporal case timelines.\"\"\"\n",
    "    # Use temporal query to analyze timelines\n",
    "    timeline = temporal_query.query_by_time_range(kg, start_date=\"2024-01-01\", end_date=\"2024-12-31\")\n",
    "    memory.store(\n",
    "        \"Timeline analysis agent built case timelines\",\n",
    "        metadata={\"agent\": \"timeline_analysis\"}\n",
    "    )\n",
    "    return {\"timeline\": timeline}\n",
    "\n",
    "# Agent 3: Cross-Case Correlation Agent\n",
    "def agent_cross_case_correlation(kg, analyzer, memory):\n",
    "    \"\"\"Agent for finding connections across cases.\"\"\"\n",
    "    # Find common suspects, locations, evidence\n",
    "    communities = analyzer.detect_communities(kg, method=\"louvain\")\n",
    "    memory.store(\n",
    "        f\"Cross-case correlation identified {communities.get('num_communities', 0) if isinstance(communities, dict) else 0} case clusters\",\n",
    "        metadata={\"agent\": \"cross_case_correlation\"}\n",
    "    )\n",
    "    return {\"case_clusters\": communities}\n",
    "\n",
    "# Agent 4: Forensic Report Agent\n",
    "def agent_forensic_report(analysis_results, memory):\n",
    "    \"\"\"Agent for generating forensic reports.\"\"\"\n",
    "    context = memory.retrieve(\"forensic analysis\", max_results=10)\n",
    "    memory.store(\n",
    "        \"Forensic report agent compiled comprehensive report\",\n",
    "        metadata={\"agent\": \"forensic_report\"}\n",
    "    )\n",
    "    return {\"report_data\": analysis_results, \"context_items\": len(context)}\n",
    "\n",
    "def evidence_collection_handler(data, **config):\n",
    "    evidence_data = data.get(\"evidence_logs_data\")\n",
    "    memory = data.get(\"memory\")\n",
    "    r = agent_evidence_collection(evidence_data, memory)\n",
    "    return {**data, \"evidence_collection_result\": r}\n",
    "def timeline_handler(data, **config):\n",
    "    kg = data.get(\"forensic_kg\")\n",
    "    temporal = data.get(\"temporal_query\")\n",
    "    memory = data.get(\"memory\")\n",
    "    r = agent_timeline_analysis(kg, temporal, memory)\n",
    "    return {**data, \"timeline_result\": r}\n",
    "def correlation_handler(data, **config):\n",
    "    kg = data.get(\"forensic_kg\")\n",
    "    analyzer = data.get(\"graph_analyzer\")\n",
    "    memory = data.get(\"memory\")\n",
    "    r = agent_cross_case_correlation(kg, analyzer, memory)\n",
    "    return {**data, \"correlation_result\": r}\n",
    "def report_handler(data, **config):\n",
    "    memory = data.get(\"memory\")\n",
    "    analysis = {\n",
    "        \"evidence\": data.get(\"evidence_collection_result\"),\n",
    "        \"timeline\": data.get(\"timeline_result\"),\n",
    "        \"correlation\": data.get(\"correlation_result\")\n",
    "    }\n",
    "    r = agent_forensic_report(analysis, memory)\n",
    "    return {**data, \"forensic_report_result\": r}\n",
    "forensic_pipeline = (\n",
    "    pipeline_builder\n",
    "    .add_step(\"evidence_collection\", \"ingest\", handler=evidence_collection_handler)\n",
    "    .add_step(\"timeline_analysis\", \"analyze_graph\", dependencies=[\"evidence_collection\"], handler=timeline_handler)\n",
    "    .add_step(\"cross_case_correlation\", \"analyze_graph\", dependencies=[\"timeline_analysis\"], handler=correlation_handler)\n",
    "    .add_step(\"forensic_report\", \"report\", dependencies=[\"cross_case_correlation\"], handler=report_handler)\n",
    ")\n",
    ".build()\n",
    "input_data = {\"evidence_logs_data\": evidence_logs_data, \"forensic_kg\": forensic_kg, \"temporal_query\": temporal_query, \"graph_analyzer\": graph_analyzer, \"memory\": agent_memory, \"cases_data\": cases_data}\n",
    "pipeline_result = execution_engine.execute_pipeline(forensic_pipeline, data=input_data, parallel=True)\n",
    "\n",
    "print(f\"  - Pipeline steps: {len(forensic_pipeline.steps)}\")\n",
    "print(f\"  - Parallel execution: Enabled\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 6: Generate Forensic Analysis Report\n",
    "\n",
    "Generate comprehensive forensic analysis report with evidence chains.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize report generator\n",
    "report_generator = ReportGenerator()\n",
    "\n",
    "# Prepare forensic report data\n",
    "forensic_report_data = {\n",
    "    \"title\": \"Forensic Analysis Report\",\n",
    "    \"executive_summary\": \"Analysis of case files, evidence chains, and cross-case correlations\",\n",
    "    \"cases_analyzed\": len(cases_data.get('cases', [])) if isinstance(cases_data, dict) else 0,\n",
    "    \"evidence_items\": len(evidence_data.get('evidence', [])) if isinstance(evidence_data, dict) else 0,\n",
    "    \"knowledge_graph\": {\n",
    "        \"entities\": len(forensic_entities),\n",
    "        \"relationships\": len(forensic_relationships)\n",
    "    },\n",
    "    \"agent_memory_stats\": agent_memory.get_statistics()\n",
    "}\n",
    "\n",
    "# Generate HTML report\n",
    "forensic_report_file = os.path.join(temp_dir, \"forensic_analysis_report.html\")\n",
    "report_generator.generate_report(\n",
    "    forensic_report_data,\n",
    "    forensic_report_file,\n",
    "    format=\"html\"\n",
    ")\n",
    "\n",
    "print(f\"  - Report file: {forensic_report_file}\")\n",
    "print(f\"  - Report includes: Case analysis, evidence chains, cross-case correlations\")\n"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
