{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# RiC-O — In-Memory Demo (NetworkX)\n", "\n", "This notebook demonstrates how to model a **RiC-O** (Records in Contexts — Ontology)\n", "graph using the DRM tools with the **NetworkX** in-memory backend.\n", "\n", "**Key concepts:**\n", "- `NetworkXGraph` stores everything in memory with optional pickle persistence\n", "- Same DRM entity classes (`Thing`, `Agent`, `RecordResource`, etc.) as Neo4j\n", "- Same `load_ric_o_naf()` loader downloads real RiC-O data from GitHub\n", "- `get_subdocuments()` traverses `_propagate` edges (BFS)\n", "- Cypher queries are supported via an in-memory executor\n", "- Persistence file is created fresh each run in `/tmp/`\n", "\n", "**Steps:**\n", "1. Create an in-memory NetworkX graph with unique persistence path\n", "2. Load real RiC-O data from the National Archives of France (NAF) example\n", "3. Initialize propagation properties\n", "4. Query subdocuments\n", "5. Inspect the hierarchy\n", "6. Summary statistics\n", "\n", "## Why NetworkX?\n", "\n", "NetworkX is useful for:\n", "- **Prototyping** — no external database needed\n", "- **Testing** — fast, deterministic, easy to clean up\n", "- **Learning** — see the graph structure without Neo4j overhead\n", "- **Persistence** — pickle file survives notebook restarts (optional)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:00.070984Z", "start_time": "2026-07-12T14:58:59.934348Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ drm already installed. Skipping.\n" ] } ], "source": [ "import importlib.util\n", "\n", "# Check if drm is installed\n", "package_to_check = 'drm'\n", "spec = importlib.util.find_spec(package_to_check)\n", "\n", "if spec is None:\n", " print(f'⚠️ {package_to_check} not installed. Installing...')\n", " %pip install -q --upgrade drm-tools\n", " print(\"✅ Installation complete.\")\n", "else:\n", " print(f'✅ {package_to_check} already installed. Skipping.')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:01.094534Z", "start_time": "2026-07-12T14:59:00.074646Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ Loaded .env from /Users/oriol/Desenvolupament/drm-tools/.env\n", " Found 5 variables\n", "✅ Added /Users/oriol/Desenvolupament/drm-tools to sys.path\n", "✅ All imports successful.\n" ] } ], "source": [ "import os\n", "import sys\n", "import uuid\n", "from pathlib import Path\n", "\n", "# Read .env file manually (no python-dotenv dependency)\n", "def read_env(env_path):\n", " \"\"\"Read a .env file and return a dict of key=value pairs.\"\"\"\n", " env_vars = {}\n", " with open(env_path, 'r') as f:\n", " for line in f:\n", " line = line.strip()\n", " if not line or line.startswith('#'):\n", " continue\n", " if '=' in line:\n", " key, value = line.split('=', 1)\n", " env_vars[key.strip()] = value.strip()\n", " return env_vars\n", "\n", "# Find .env in repo root\n", "_env_path = Path.cwd() / \".env\"\n", "if not _env_path.exists():\n", " for parent in Path.cwd().parents:\n", " candidate = parent / \".env\"\n", " if candidate.exists():\n", " _env_path = candidate\n", " break\n", "\n", "if _env_path.exists():\n", " _env_vars = read_env(_env_path)\n", " for key, value in _env_vars.items():\n", " os.environ.setdefault(key, value)\n", " print(f\"✅ Loaded .env from {_env_path}\")\n", " print(f\" Found {len(_env_vars)} variables\")\n", "else:\n", " print(\"⚠️ .env file not found. NetworkX backend doesn't need credentials.\")\n", "\n", "# Add drm package to path for development\n", "_repo_root = Path.cwd()\n", "if not (_repo_root / \"drm\").exists():\n", " for parent in Path.cwd().parents:\n", " if (parent / \"drm\").exists():\n", " _repo_root = parent\n", " break\n", "# Add repo root to sys.path so local drm loads before PyPI version\n", "if str(_repo_root) not in sys.path:\n", " sys.path.insert(0, str(_repo_root))\n", " print(f\"✅ Added {_repo_root} to sys.path\")\n", "\n", "from drm.networkx_graph import NetworkXGraph\n", "from drm.rico_entities import (\n", " Thing,\n", " Agent, Person, CorporateBody, AgentName, Appellation,\n", " Date, Place, PlaceName, Event, Activity,\n", " RecordResource, Instantiation, Title,\n", " Group, Name,\n", ")\n", "\n", "def section(title):\n", " \"\"\"Print a section header.\"\"\"\n", " print(f\"\\n{'=' * 60}\")\n", " print(f\" {title}\")\n", " print(f\"{'=' * 60}\")\n", "\n", "def sub_section(title):\n", " \"\"\"Print a subsection header.\"\"\"\n", " print(f\"\\n--- {title} ---\")\n", "\n", "print(\"✅ All imports successful.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 1: Create in-memory graph with unique persistence path\n", "\n", "The NetworkX backend stores data in memory. A pickle file is used for\n", "persistence across notebook restarts. Each run creates a **unique** file\n", "using a UUID, so previous runs never interfere." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:01.221279Z", "start_time": "2026-07-12T14:59:01.179926Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "📁 Persistence file: /var/folders/rm/5_s35r9j3198mxxpvlpfx8700000gn/T/ric_o_networkx_e073bd7a.pkl\n", " (unique per run — safe to delete after)\n", "\n", "✅ NetworkXGraph created.\n", " Nodes in memory: 0\n", " Edges in memory: 0\n", " Persistence enabled: True\n" ] } ], "source": [ "import os\n", "import tempfile\n", "\n", "# Generate a unique persistence file for this run\n", "_run_id = uuid.uuid4().hex[:8]\n", "_persistence_file = os.path.join(\n", " tempfile.gettempdir(),\n", " f\"ric_o_networkx_{_run_id}.pkl\"\n", ")\n", "\n", "print(f\"📁 Persistence file: {_persistence_file}\")\n", "print(f\" (unique per run — safe to delete after)\")\n", "\n", "# Create the in-memory graph\n", "graph = NetworkXGraph(persistence_path=_persistence_file)\n", "\n", "print(f\"\\n✅ NetworkXGraph created.\")\n", "print(f\" Nodes in memory: {len(graph._node_attrs)}\")\n", "print(f\" Edges in memory: {len(graph._graph.edges())}\")\n", "print(f\" Persistence enabled: {graph._persistence_path is not None}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 2: Load real RiC-O data from the National Archives of France\n", "\n", "The DRM tools include a loader that downloads and parses RiC-O RDF/XML data\n", "from the [ICA-EGAD/RiC-O repository](https://github.com/ICA-EGAD/RiC-O/tree/master/examples/examples_v1-1/NationalArchivesOfFrance).\n", "\n", "**What gets loaded:**\n", "\n", "| RDF Type | DRM Entity | Parent |\n", "|----------|-----------|--------|\n", "| `rico:Record` | `Thing` | — (strong node) |\n", "| `rico:Agent` | `Agent` | `Thing` |\n", "| `rico:CorporateBody` | `CorporateBody` | `Agent` |\n", "| `rico:Individual` | `Person` | `Agent` |\n", "| `rico:AgentName` | `AgentName` | `Agent`/`Person` |\n", "| `rico:RecordResource` | `RecordResource` | `Thing` |\n", "| `rico:Instantiation` | `Instantiation` | `Thing`/`RecordResource` |\n", "| `rico:Activity` | `Activity` | `Thing` |\n", "\n", "**Hierarchy example:**\n", "```\n", "Thing (strong)\n", "├── Agent (WeakNode)\n", "│ ├── AgentName (WeakNode of Agent)\n", "│ └── Instantiation (WeakNode of Agent)\n", "└── RecordResource (WeakNode)\n", " └── Instantiation (WeakNode of RecordResource)\n", "```\n", "\n", "The loader downloads files from GitHub, parses the RDF/XML, and inserts\n", "entities into the graph with proper parent-child relationships." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:06.648289Z", "start_time": "2026-07-12T14:59:01.241869Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "============================================================\n", " Loading RiC-O data from National Archives of France\n", "============================================================\n", "\n", "📊 Load statistics:\n", " Agents loaded: 10\n", " Records loaded: 27\n", " Things created: 40\n", " Child entities: 75\n", " Total entities: 152\n" ] } ], "source": [ "from drm.exemples import load_ric_o_naf\n", "\n", "section(\"Loading RiC-O data from National Archives of France\")\n", "\n", "# Load real RiC-O data\n", "# limit: total entities to load (soft limit)\n", "# max_agents: number of agent files to load\n", "# max_records: number of record resource files to load\n", "stats = load_ric_o_naf(\n", " graph,\n", " limit=50,\n", " max_agents=10,\n", " max_records=3,\n", ")\n", "\n", "print(f\"\\n📊 Load statistics:\")\n", "print(f\" Agents loaded: {stats['agents']}\")\n", "print(f\" Records loaded: {stats['records']}\")\n", "print(f\" Things created: {stats['things']}\")\n", "print(f\" Child entities: {stats.get('children', '?')}\")\n", "print(f\" Total entities: {stats['total']}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 3: Initialize propagation properties\n", "\n", "Scan the graph and initialize `_propagate` flags on edges between\n", "parent and child nodes. This enables cascade delete behavior.\n", "\n", "In NetworkX, this is much faster than Neo4j since everything is in memory." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:06.731225Z", "start_time": "2026-07-12T14:59:06.672595Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "--- Before init_propagation() ---\n", " Total nodes: 152\n", " Nodes with is_weak: 0\n", " Nodes with _weak_init_done: 0\n", "\n", "Running init_propagation()...\n", "Result: True\n", "\n", "--- After init_propagation() ---\n", " Total nodes: 152\n", " Nodes with is_weak: 112\n", " Nodes with _weak_init_done: 0\n", " Edges with _propagate: 112\n" ] } ], "source": [ "# Check state before init (using internal attributes)\n", "sub_section(\"Before init_propagation()\")\n", "total_before = len(graph._node_attrs)\n", "weak_before = sum(1 for a in graph._node_attrs.values() if a.get('is_weak'))\n", "done_before = sum(1 for a in graph._node_attrs.values() if a.get('_weak_init_done'))\n", "print(f\" Total nodes: {total_before}\")\n", "print(f\" Nodes with is_weak: {weak_before}\")\n", "print(f\" Nodes with _weak_init_done: {done_before}\")\n", "\n", "# Run initialization\n", "print(\"\\nRunning init_propagation()...\")\n", "init_result = graph.init_propagation()\n", "print(f\"Result: {init_result}\")\n", "\n", "# Check state after init\n", "sub_section(\"After init_propagation()\")\n", "total_after = len(graph._node_attrs)\n", "weak_after = sum(1 for a in graph._node_attrs.values() if a.get('is_weak'))\n", "done_after = sum(1 for a in graph._node_attrs.values() if a.get('_weak_init_done'))\n", "print(f\" Total nodes: {total_after}\")\n", "print(f\" Nodes with is_weak: {weak_after}\")\n", "print(f\" Nodes with _weak_init_done: {done_after}\")\n", "\n", "# Count propagation edges\n", "prop_count = sum(\n", " 1 for u, v, k, d in graph._graph.edges(data=True, keys=True)\n", " if graph.get_edge_attrs(u, v, d.get('rel_type', k)).get('_propagate') is True\n", ")\n", "print(f\" Edges with _propagate: {prop_count}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 4: Inspect the loaded graph structure\n", "\n", "Query the graph to see what entities were loaded and how they are organized.\n", "We use the internal `_node_attrs` and `_edge_attrs` dicts for inspection,\n", "which works regardless of Cypher executor limitations." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:06.798272Z", "start_time": "2026-07-12T14:59:06.736942Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "--- Nodes by label ---\n", " AgentName: 48\n", " Thing: 40\n", " RecordResource: 27\n", " Instantiation: 27\n", " Agent: 10\n", "\n", "--- Relations by type ---\n", " HAS_*: 112\n" ] } ], "source": [ "# Show all Things (strong nodes)\n", "sub_section(\"Nodes by label\")\n", "from collections import Counter\n", "label_counts = Counter(a.get('main_label', 'Node') for a in graph._node_attrs.values())\n", "for label, count in label_counts.most_common():\n", " print(f\" {label}: {count}\")\n", "\n", "# Show relations by type\n", "sub_section(\"Relations by type\")\n", "rel_counts = Counter()\n", "for u, v, k, d in graph._graph.edges(data=True, keys=True):\n", " edge_attrs = graph.get_edge_attrs(u, v, d.get('rel_type', k))\n", " rel_type = edge_attrs.get('_propagate', False) and 'HAS_*' or d.get('rel_type', k)\n", " rel_counts[rel_type] += 1\n", "for rel_type, count in rel_counts.most_common():\n", " print(f\" {rel_type}: {count}\")\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:06.856568Z", "start_time": "2026-07-12T14:59:06.804061Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "--- All Things (strong nodes) ---\n", " record-000005: record-000005\n", " record-000016: record-000016\n", " record-000051: record-000051\n", " record-003500: record-003500\n", " record-003529: record-003529\n", " record-003530: record-003530\n", " record-003531: record-003531\n", " record-003532: record-003532\n", " record-003549: record-003549\n", " record-003550: record-003550\n", " record-003551: record-003551\n", " record-007375: record-007375\n", " record-009555: record-009555\n", " thing-rr-recordResource-recordResource-003500-d_1: thing-rr-recordResource-recordResource-003500-d_1\n", " thing-rr-recordResource-recordResource-003500-d_2: thing-rr-recordResource-recordResource-003500-d_2\n", " thing-rr-recordResource-recordResource-003500-d_3: thing-rr-recordResource-recordResource-003500-d_3\n", " thing-rr-recordResource-recordResource-003500-d_4: thing-rr-recordResource-recordResource-003500-d_4\n", " thing-rr-recordResource-recordResource-007375-d_1: thing-rr-recordResource-recordResource-007375-d_1\n", " thing-rr-recordResource-recordResource-007375-d_2: thing-rr-recordResource-recordResource-007375-d_2\n", " thing-rr-recordResource-recordResource-009555-d_1: thing-rr-recordResource-recordResource-009555-d_1\n", " thing-rr-recordResource-recordResource-009555-d_10: thing-rr-recordResource-recordResource-009555-d_10\n", " thing-rr-recordResource-recordResource-009555-d_11: thing-rr-recordResource-recordResource-009555-d_11\n", " thing-rr-recordResource-recordResource-009555-d_12: thing-rr-recordResource-recordResource-009555-d_12\n", " thing-rr-recordResource-recordResource-009555-d_13: thing-rr-recordResource-recordResource-009555-d_13\n", " thing-rr-recordResource-recordResource-009555-d_14: thing-rr-recordResource-recordResource-009555-d_14\n", " thing-rr-recordResource-recordResource-009555-d_15: thing-rr-recordResource-recordResource-009555-d_15\n", " thing-rr-recordResource-recordResource-009555-d_16: thing-rr-recordResource-recordResource-009555-d_16\n", " thing-rr-recordResource-recordResource-009555-d_17: thing-rr-recordResource-recordResource-009555-d_17\n", " thing-rr-recordResource-recordResource-009555-d_18: thing-rr-recordResource-recordResource-009555-d_18\n", " thing-rr-recordResource-recordResource-009555-d_2: thing-rr-recordResource-recordResource-009555-d_2\n", " thing-rr-recordResource-recordResource-009555-d_3: thing-rr-recordResource-recordResource-009555-d_3\n", " thing-rr-recordResource-recordResource-009555-d_4: thing-rr-recordResource-recordResource-009555-d_4\n", " thing-rr-recordResource-recordResource-009555-d_5: thing-rr-recordResource-recordResource-009555-d_5\n", " thing-rr-recordResource-recordResource-009555-d_6: thing-rr-recordResource-recordResource-009555-d_6\n", " thing-rr-recordResource-recordResource-009555-d_7: thing-rr-recordResource-recordResource-009555-d_7\n", " thing-rr-recordResource-recordResource-009555-d_8: thing-rr-recordResource-recordResource-009555-d_8\n", " thing-rr-recordResource-recordResource-009555-d_9: thing-rr-recordResource-recordResource-009555-d_9\n", " thing-rr-recordResource-recordResource-top-003500: thing-rr-recordResource-recordResource-top-003500\n", " thing-rr-recordResource-recordResource-top-007375: thing-rr-recordResource-recordResource-top-007375\n", " thing-rr-recordResource-recordResource-top-009555: thing-rr-recordResource-recordResource-top-009555\n" ] } ], "source": [ "# Show all Things (strong nodes)\n", "sub_section(\"All Things (strong nodes)\")\n", "things = [\n", " (nid, a.get('identifier', '?'), a.get('title', a.get('identifier', '?')))\n", " for nid, a in graph._node_attrs.items()\n", " if a.get('main_label') == 'Thing'\n", "]\n", "things.sort(key=lambda x: x[1])\n", "for nid, identifier, name in things:\n", " print(f\" {identifier}: {name}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 5: Get subdocuments\n", "\n", "Use `get_subdocuments()` to retrieve all weak descendants of each `Thing`.\n", "This traverses only edges with `_propagate=True` using BFS." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:06.928156Z", "start_time": "2026-07-12T14:59:06.860865Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "--- Subdocuments of Thing(record-000005) ---\n", " Found 13 subdocuments:\n", " - Agent: agent-agent-000005\n", " - AgentName: France. Ministère de la Culture et de la Communication (1959-....)\n", " - AgentName: Ministère de la Culture\n", " - AgentName: Ministère de la Culture et de la Communication\n", " - AgentName: Ministère de la Culture, de la Communication, des Grands Travaux et du Bicentenaire\n", " - AgentName: Ministère de la Culture et de la Communication\n", " ... and 7 more\n", "\n", "--- Subdocuments of Thing(record-000016) ---\n", " Found 11 subdocuments:\n", " - Agent: agent-agent-000016\n", " - AgentName: France. Ministère de l'Éducation nationale (1828-....)\n", " - AgentName: Ministère de l'Éducation nationale, de la Jeunesse et de la Vie associative\n", " - AgentName: Ministère de l'Éducation nationale\n", " - AgentName: Ministère de l'Éducation nationale, de l'Enseignement supérieur et de la Recherche\n", " - AgentName: Ministère de la Jeunesse, de l'Éducation nationale et de la Recherche\n", " ... and 5 more\n", "\n", "--- Subdocuments of Thing(record-000051) ---\n", " Found 4 subdocuments:\n", " - Agent: agent-agent-000051\n", " - AgentName: France. Ministère des affaires culturelles. Direction de l'architecture (1959-1978)\n", " - AgentName: France. Ministère de la culture et de l'environnement. Direction de l'architecture\n", " - AgentName: France. Secrétariat d'État à la culture. Direction de l'architecture\n", "\n", "--- Subdocuments of Thing(record-003500) ---\n", " Found 0 subdocuments:\n", "\n", "--- Subdocuments of Thing(record-003529) ---\n", " Found 8 subdocuments:\n", " - Agent: agent-agent-003529\n", " - AgentName: France. Direction des bibliothèques et de la lecture publique. Bureau de la gestion et du contrôle financiers (1945-1975)\n", " - AgentName: Bureau de la gestion et du contrôle financier\n", " - AgentName: Deuxième bureau (Gestion et contrôle financier, Affaires générales-Documentation-Matériel)\n", " - AgentName: Bureau de la gestion et du contrôle financiers\n", " - AgentName: Bureau de la comptabilité\n", " ... and 2 more\n", "\n", "--- Subdocuments of Thing(record-003530) ---\n", " Found 4 subdocuments:\n", " - Agent: agent-agent-003530\n", " - AgentName: France. Direction des bibliothèques et de la lecture publique. Division des services administratifs. Bureau des affaires générales (1965-1975)\n", " - AgentName: DB 3\n", " - AgentName: BL 3\n", "\n", "--- Subdocuments of Thing(record-003531) ---\n", " Found 7 subdocuments:\n", " - Agent: agent-agent-003531\n", " - AgentName: France. Direction des bibliothèques et de la lecture publique. Bureau du personnel (1945-1975)\n", " - AgentName: Bureau du personnel\n", " - AgentName: Bureau du personnel et des affaires générales\n", " - AgentName: Bureau du personnel\n", " - AgentName: BL 1\n", " ... and 1 more\n", "\n", "--- Subdocuments of Thing(record-003532) ---\n", " Found 4 subdocuments:\n", " - Agent: agent-agent-003532\n", " - AgentName: France. Direction des bibliothèques et de la lecture publique. Division des affaires administratives (1965-1975)\n", " - AgentName: Services administratifs\n", " - AgentName: Division des affaires administratives\n", "\n", "--- Subdocuments of Thing(record-003549) ---\n", " Found 2 subdocuments:\n", " - Agent: agent-agent-003549\n", " - AgentName: France. Direction des bibliothèques et de la lecture publique. Services techniques. Section des bibliothèques d'étude et de recherche (1971-1975)\n", "\n", "--- Subdocuments of Thing(record-003550) ---\n", " Found 2 subdocuments:\n", " - Agent: agent-agent-003550\n", " - AgentName: France. Direction des bibliothèques et de la lecture publique. Services techniques. Section des affaires communes (1971-1975)\n", "\n", "--- Subdocuments of Thing(record-003551) ---\n", " Found 3 subdocuments:\n", " - Agent: agent-agent-003551\n", " - AgentName: France. Direction des bibliothèques et de la lecture publique. Services techniques. Section de la lecture publique (1968-1975)\n", " - AgentName: Service de la lecture publique\n", "\n", "--- Subdocuments of Thing(record-007375) ---\n", " Found 0 subdocuments:\n", "\n", "--- Subdocuments of Thing(record-009555) ---\n", " Found 0 subdocuments:\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-003500-d_1) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-003500-d_2) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-003500-d_3) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-003500-d_4) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-007375-d_1) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-007375-d_2) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_1) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_10) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_11) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_12) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_13) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_14) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_15) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_16) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_17) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_18) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_2) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_3) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_4) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_5) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_6) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_7) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_8) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-009555-d_9) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-top-003500) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-top-007375) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n", "\n", "--- Subdocuments of Thing(thing-rr-recordResource-recordResource-top-009555) ---\n", " Found 2 subdocuments:\n", " - Instantiation: ?\n", " - RecordResource: ?\n" ] } ], "source": [ "# Show subdocuments for each Thing\n", "for nid, identifier, name in things:\n", " thing_node = Thing(pk={\"identifier\": identifier})\n", " subdocs = graph.get_subdocuments(thing_node)\n", " \n", " sub_section(f\"Subdocuments of Thing({identifier})\")\n", " print(f\" Found {len(subdocs)} subdocuments:\")\n", " \n", " # Group by label\n", " by_label = {}\n", " for sd in subdocs:\n", " label = sd['label']\n", " if label not in by_label:\n", " by_label[label] = []\n", " by_label[label].append(sd)\n", " \n", " for label in sorted(by_label.keys()):\n", " items = by_label[label]\n", " for item in items[:5]: # Show max 5 per label\n", " name = item['pk'].get('fullName', item['pk'].get('name', item['pk'].get('agentId', '?')))\n", " print(f\" - {label}: {name}\")\n", " if len(items) > 5:\n", " print(f\" ... and {len(items) - 5} more\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 6: Query the hierarchy paths\n", "\n", "Visualize the full hierarchy for a sample `Thing` by walking the NetworkX graph directly.\n", "This avoids Cypher executor limitations for path traversal." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:07.015060Z", "start_time": "2026-07-12T14:59:06.959596Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "--- Hierarchy: Thing(record-000005) ---\n", " Thing(string) → Agent(agent-agent-000005) → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(France. Ministère de la Culture et de la Communication (1959-....)) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de la Communication) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture, de la Communication, des Grands Travaux et du Bicentenaire) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de la Communication) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de la Communication) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de l'Environnement) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Secrétariat d'État à la Culture) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère des Affaires culturelles) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère des Affaires culturelles et de l'Environnement) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de la Francophonie) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(France. Ministère de la Culture et de la Communication (1959-....)) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de la Communication) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture, de la Communication, des Grands Travaux et du Bicentenaire) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de la Communication) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de la Communication) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de l'Environnement) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Secrétariat d'État à la Culture) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère des Affaires culturelles) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère des Affaires culturelles et de l'Environnement) → -[parent]-> → -[parent]->\n", " Thing(string) → Agent(agent-agent-000005) → AgentName(Ministère de la Culture et de la Francophonie) → -[parent]-> → -[parent]->\n" ] } ], "source": [ "def _walk_hierarchy(graph, start_id, max_depth=6):\n", " \"\"\"Walk the graph from start_id and return all reachable nodes.\"\"\"\n", " paths = []\n", " queue = [(start_id, [start_id], [])]\n", " \n", " while queue:\n", " current, path_nodes, path_edges = queue.pop(0)\n", " \n", " if len(path_nodes) > 1:\n", " paths.append((path_nodes, path_edges))\n", " \n", " if len(path_nodes) >= max_depth:\n", " continue\n", " \n", " # MultiDiGraph.edges(u, data=True, keys=True) yields (u, v, key, data)\n", " for u, v, edge_key, edge_data in graph._graph.edges(current, data=True, keys=True):\n", " edge_attrs = graph.get_edge_attrs(u, v, edge_data.get('rel_type', edge_key))\n", " rel_type = edge_attrs.get('_propagate', False) and 'parent' or edge_data.get('rel_type', 'unknown')\n", " paths.append((path_nodes + [v], path_edges + [(u, v, rel_type)]))\n", " if len(path_nodes) < max_depth - 1:\n", " queue.append((v, path_nodes + [v], path_edges + [(u, v, rel_type)]))\n", " \n", " return paths\n", "\n", "# Walk hierarchy for first Thing\n", "if things:\n", " first_nid, first_id, first_name = things[0]\n", " \n", " sub_section(f\"Hierarchy: Thing({first_id})\")\n", " \n", " paths = _walk_hierarchy(graph, first_nid)\n", " for path_nodes, path_edges in paths:\n", " parts = []\n", " for node_id in path_nodes:\n", " attrs = graph._node_attrs.get(node_id, {})\n", " label = attrs.get('main_label', 'Node')\n", " name = attrs.get('fullName', attrs.get('name', attrs.get('agentId', attrs.get('recordResourceId', str(node_id)))))\n", " parts.append(f\"{label}({name})\")\n", " for src, dst, rel_type in path_edges:\n", " parts.append(f\"-[{rel_type}]->\")\n", " print(f\" {' → '.join(parts)}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 7: Inspect specific entities\n", "\n", "Look at the properties of loaded entities to understand the data model." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:07.175397Z", "start_time": "2026-07-12T14:59:07.018598Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "--- Sample Agent entities ---\n", " agent-agent-000005: No label\n", " Born: 1959-01-08, Died: N/A\n", " agent-agent-000016: No label\n", " Born: 1828-02-10, Died: N/A\n", " agent-agent-000051: No label\n", " Born: 1959-01-01, Died: 1978-12-31\n", " agent-agent-003529: No label\n", " Born: 1945-08-18, Died: 1975-12-31\n", " agent-agent-003530: No label\n", " Born: 1965-01-01, Died: 1975-12-31\n", "\n", "--- Sample RecordResource entities ---\n", " recordResource-recordResource-003500-d_1: LUDOVIC VITET (1802-1873)\n", " Date range: N/A — N/A\n", " recordResource-recordResource-003500-d_2: EUGENE AUBRY-VITET (1845-1930) 1\n", " Date range: N/A — N/A\n", " recordResource-recordResource-003500-d_3: FAMILLE COSTA DE BEAUREGARD 1.\n", " Date range: N/A — N/A\n", " recordResource-recordResource-003500-d_4: COLLECTION DE PHOTOGRAPHIES.\n", " Date range: N/A — N/A\n", " recordResource-recordResource-007375-d_1: FRANCE\n", " Date range: N/A — N/A\n" ] } ], "source": [ "# Show sample Agent entities\n", "sub_section(\"Sample Agent entities\")\n", "agents = [\n", " (nid, a.get('agentId', '?'), a.get('label', 'No label'),\n", " a.get('beginningDate', ''), a.get('endDate', ''))\n", " for nid, a in graph._node_attrs.items()\n", " if a.get('main_label') in ('Agent', 'CorporateBody', 'Person', 'Family')\n", "]\n", "agents.sort(key=lambda x: x[1])\n", "for nid, agent_id, label, birth, death in agents[:5]:\n", " print(f\" {agent_id}: {label}\")\n", " print(f\" Born: {birth or 'N/A'}, Died: {death or 'N/A'}\")\n", "\n", "# Show sample RecordResource entities\n", "sub_section(\"Sample RecordResource entities\")\n", "record_resources = [\n", " (nid, a.get('recordResourceId', '?'), a.get('title', ''),\n", " a.get('beginningDate', ''), a.get('endDate', ''))\n", " for nid, a in graph._node_attrs.items()\n", " if a.get('main_label') == 'RecordResource'\n", "]\n", "record_resources.sort(key=lambda x: x[1])\n", "for nid, rr_id, title, from_date, to_date in record_resources[:5]:\n", " print(f\" {rr_id}: {title or 'No title'}\")\n", " print(f\" Date range: {from_date or 'N/A'} — {to_date or 'N/A'}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 8: Summary statistics\n", "\n", "Show the final state of the RiC-O graph." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:07.391817Z", "start_time": "2026-07-12T14:59:07.204210Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "============================================================\n", " Final summary\n", "============================================================\n", "\n", "--- Nodes by label ---\n", " AgentName: 48\n", " Thing: 40\n", " RecordResource: 27\n", " Instantiation: 27\n", " Agent: 10\n", "\n", "--- Propagation edges by type ---\n", " HAS_AGENTNAME: 48\n", " HAS_RECORDRESOURCE: 27\n", " HAS_INSTANTIATION: 27\n", " HAS_AGENT: 10\n", "\n", "--- All Things ---\n", " record-000005: record-000005\n", " record-000016: record-000016\n", " record-000051: record-000051\n", " record-003500: record-003500\n", " record-003529: record-003529\n", " record-003530: record-003530\n", " record-003531: record-003531\n", " record-003532: record-003532\n", " record-003549: record-003549\n", " record-003550: record-003550\n", " record-003551: record-003551\n", " record-007375: record-007375\n", " record-009555: record-009555\n", " thing-rr-recordResource-recordResource-003500-d_1: thing-rr-recordResource-recordResource-003500-d_1\n", " thing-rr-recordResource-recordResource-003500-d_2: thing-rr-recordResource-recordResource-003500-d_2\n", " thing-rr-recordResource-recordResource-003500-d_3: thing-rr-recordResource-recordResource-003500-d_3\n", " thing-rr-recordResource-recordResource-003500-d_4: thing-rr-recordResource-recordResource-003500-d_4\n", " thing-rr-recordResource-recordResource-007375-d_1: thing-rr-recordResource-recordResource-007375-d_1\n", " thing-rr-recordResource-recordResource-007375-d_2: thing-rr-recordResource-recordResource-007375-d_2\n", " thing-rr-recordResource-recordResource-009555-d_1: thing-rr-recordResource-recordResource-009555-d_1\n", " thing-rr-recordResource-recordResource-009555-d_10: thing-rr-recordResource-recordResource-009555-d_10\n", " thing-rr-recordResource-recordResource-009555-d_11: thing-rr-recordResource-recordResource-009555-d_11\n", " thing-rr-recordResource-recordResource-009555-d_12: thing-rr-recordResource-recordResource-009555-d_12\n", " thing-rr-recordResource-recordResource-009555-d_13: thing-rr-recordResource-recordResource-009555-d_13\n", " thing-rr-recordResource-recordResource-009555-d_14: thing-rr-recordResource-recordResource-009555-d_14\n", " thing-rr-recordResource-recordResource-009555-d_15: thing-rr-recordResource-recordResource-009555-d_15\n", " thing-rr-recordResource-recordResource-009555-d_16: thing-rr-recordResource-recordResource-009555-d_16\n", " thing-rr-recordResource-recordResource-009555-d_17: thing-rr-recordResource-recordResource-009555-d_17\n", " thing-rr-recordResource-recordResource-009555-d_18: thing-rr-recordResource-recordResource-009555-d_18\n", " thing-rr-recordResource-recordResource-009555-d_2: thing-rr-recordResource-recordResource-009555-d_2\n", " thing-rr-recordResource-recordResource-009555-d_3: thing-rr-recordResource-recordResource-009555-d_3\n", " thing-rr-recordResource-recordResource-009555-d_4: thing-rr-recordResource-recordResource-009555-d_4\n", " thing-rr-recordResource-recordResource-009555-d_5: thing-rr-recordResource-recordResource-009555-d_5\n", " thing-rr-recordResource-recordResource-009555-d_6: thing-rr-recordResource-recordResource-009555-d_6\n", " thing-rr-recordResource-recordResource-009555-d_7: thing-rr-recordResource-recordResource-009555-d_7\n", " thing-rr-recordResource-recordResource-009555-d_8: thing-rr-recordResource-recordResource-009555-d_8\n", " thing-rr-recordResource-recordResource-009555-d_9: thing-rr-recordResource-recordResource-009555-d_9\n", " thing-rr-recordResource-recordResource-top-003500: thing-rr-recordResource-recordResource-top-003500\n", " thing-rr-recordResource-recordResource-top-007375: thing-rr-recordResource-recordResource-top-007375\n", " thing-rr-recordResource-recordResource-top-009555: thing-rr-recordResource-recordResource-top-009555\n", "\n", "--- Subdocuments per Thing ---\n", " record-000005: 13 subdocuments\n", " record-000016: 11 subdocuments\n", " record-000051: 4 subdocuments\n", " record-003500: 0 subdocuments\n", " record-003529: 8 subdocuments\n", " record-003530: 4 subdocuments\n", " record-003531: 7 subdocuments\n", " record-003532: 4 subdocuments\n", " record-003549: 2 subdocuments\n", " record-003550: 2 subdocuments\n", " record-003551: 3 subdocuments\n", " record-007375: 0 subdocuments\n", " record-009555: 0 subdocuments\n", " thing-rr-recordResource-recordResource-003500-d_1: 2 subdocuments\n", " thing-rr-recordResource-recordResource-003500-d_2: 2 subdocuments\n", " thing-rr-recordResource-recordResource-003500-d_3: 2 subdocuments\n", " thing-rr-recordResource-recordResource-003500-d_4: 2 subdocuments\n", " thing-rr-recordResource-recordResource-007375-d_1: 2 subdocuments\n", " thing-rr-recordResource-recordResource-007375-d_2: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_1: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_10: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_11: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_12: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_13: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_14: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_15: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_16: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_17: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_18: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_2: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_3: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_4: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_5: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_6: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_7: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_8: 2 subdocuments\n", " thing-rr-recordResource-recordResource-009555-d_9: 2 subdocuments\n", " thing-rr-recordResource-recordResource-top-003500: 2 subdocuments\n", " thing-rr-recordResource-recordResource-top-007375: 2 subdocuments\n", " thing-rr-recordResource-recordResource-top-009555: 2 subdocuments\n", "\n", "--- Persistence file ---\n", " Path: /var/folders/rm/5_s35r9j3198mxxpvlpfx8700000gn/T/ric_o_networkx_e073bd7a.pkl\n", " Size: 60,780 bytes (59.4 KB)\n", "\n", "============================================================\n", " ✅ RiC-O NetworkX demo completed successfully!\n", "============================================================\n" ] } ], "source": [ "section(\"Final summary\")\n", "\n", "# Nodes by label\n", "sub_section(\"Nodes by label\")\n", "label_counts = Counter(a.get('main_label', 'Node') for a in graph._node_attrs.values())\n", "for label, count in label_counts.most_common():\n", " print(f\" {label}: {count}\")\n", "\n", "# Propagation edges\n", "sub_section(\"Propagation edges by type\")\n", "prop_rel_counts = Counter()\n", "for u, v, k, d in graph._graph.edges(data=True, keys=True):\n", " edge_attrs = graph.get_edge_attrs(u, v, d.get('rel_type', k))\n", " if edge_attrs.get('_propagate') is True:\n", " rel_type = d.get('rel_type', k) or edge_attrs.get('_propagate', False) and 'parent' or 'unknown'\n", " prop_rel_counts[rel_type] += 1\n", "for rel_type, count in prop_rel_counts.most_common():\n", " print(f\" {rel_type}: {count}\")\n", "\n", "# All Things\n", "sub_section(\"All Things\")\n", "for nid, identifier, name in things:\n", " print(f\" {identifier}: {name}\")\n", "\n", "# Subdocument counts\n", "sub_section(\"Subdocuments per Thing\")\n", "for nid, identifier, name in things:\n", " thing_node = Thing(pk={\"identifier\": identifier})\n", " subdocs = graph.get_subdocuments(thing_node)\n", " print(f\" {identifier}: {len(subdocs)} subdocuments\")\n", "\n", "# Persistence file info\n", "sub_section(\"Persistence file\")\n", "print(f\" Path: {_persistence_file}\")\n", "if os.path.exists(_persistence_file):\n", " size = os.path.getsize(_persistence_file)\n", " print(f\" Size: {size:,} bytes ({size / 1024:.1f} KB)\")\n", "else:\n", " print(\" File not found (data only in memory)\")\n", "\n", "print(\"\\n\" + \"=\" * 60)\n", "print(\" ✅ RiC-O NetworkX demo completed successfully!\")\n", "print(\"=\" * 60)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cleanup\n", "\n", "Close the graph and optionally delete the persistence file." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "ExecuteTime": { "end_time": "2026-07-12T14:59:07.459206Z", "start_time": "2026-07-12T14:59:07.411318Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ NetworkXGraph closed.\n", "✅ Persistence file deleted: /var/folders/rm/5_s35r9j3198mxxpvlpfx8700000gn/T/ric_o_networkx_e073bd7a.pkl\n" ] } ], "source": [ "graph.close()\n", "print(\"✅ NetworkXGraph closed.\")\n", "\n", "# Clean up persistence file\n", "if os.path.exists(_persistence_file):\n", " os.remove(_persistence_file)\n", " print(f\"✅ Persistence file deleted: {_persistence_file}\")\n", "else:\n", " print(f\"ℹ️ No persistence file to clean up\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python (drm-tools)", "language": "python", "name": "drm-env" }, "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.14" } }, "nbformat": 4, "nbformat_minor": 4 }