{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# PCSWMM AI Engineering Dashboard v0.2.1\n", "\n", "Read-only dashboard. Open a PCSWMM project first." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Load SDK" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import sys\n", "import importlib\n", "from pathlib import Path\n", "\n", "REQUIRED_SDK_VERSION = \"0.2.1\"\n", "NOTEBOOK_ROOT = Path.cwd()\n", "\n", "# PCSWMM JupyterLab starts in the main Notebooks directory, not in the\n", "# notebook's own folder. Select v0.2.1 explicitly instead of taking the\n", "# first pcswmm_ai directory found by rglob().\n", "preferred_roots = [\n", " NOTEBOOK_ROOT / \"PCSWMM_AI_SDK_v0_2_1\",\n", " NOTEBOOK_ROOT / \"PCSWMM_AI_SDK_v0_2_1\" / \"PCSWMM_AI_SDK_v0_2_1\",\n", " NOTEBOOK_ROOT / \"PCSWMM_AI_SDK_v0_2\",\n", " NOTEBOOK_ROOT / \"PCSWMM_AI_SDK_v0_2\" / \"PCSWMM_AI_SDK_v0_2\",\n", "]\n", "\n", "SDK_ROOT = next(\n", " (path for path in preferred_roots if (path / \"pcswmm_ai\").is_dir()),\n", " None,\n", ")\n", "\n", "if SDK_ROOT is None:\n", " candidates = sorted(\n", " {\n", " package_dir.parent\n", " for package_dir in NOTEBOOK_ROOT.rglob(\"pcswmm_ai\")\n", " if package_dir.is_dir()\n", " and \"v0_2\" in str(package_dir.parent).lower()\n", " },\n", " reverse=True,\n", " )\n", " SDK_ROOT = candidates[0] if candidates else None\n", "\n", "if SDK_ROOT is None:\n", " raise FileNotFoundError(\n", " \"Could not locate PCSWMM AI SDK v0.2.x below:\\n\"\n", " f\"{NOTEBOOK_ROOT}\"\n", " )\n", "\n", "# Remove an earlier SDK version already cached by this kernel.\n", "for module_name in list(sys.modules):\n", " if module_name == \"pcswmm_ai\" or module_name.startswith(\"pcswmm_ai.\"):\n", " del sys.modules[module_name]\n", "\n", "# Put the selected SDK ahead of v0.1 and all other paths.\n", "sys.path = [\n", " path for path in sys.path\n", " if \"PCSWMM_AI_SDK_v0_1\" not in str(path)\n", " and \"PCSWMM_AI_SDK_v0_2\" not in str(path)\n", "]\n", "sys.path.insert(0, str(SDK_ROOT))\n", "importlib.invalidate_caches()\n", "\n", "from pcswmm_ai import PCSWMMClient, __version__ as SDK_VERSION\n", "import pcswmm_ai\n", "\n", "print(\"SDK root:\", SDK_ROOT)\n", "print(\"SDK package:\", Path(pcswmm_ai.__file__).resolve())\n", "print(\"SDK version:\", SDK_VERSION)\n", "\n", "if SDK_VERSION not in {\"0.2.0\", REQUIRED_SDK_VERSION}:\n", " raise RuntimeError(\n", " f\"Wrong SDK version loaded: {SDK_VERSION}. \"\n", " f\"Expected {REQUIRED_SDK_VERSION}.\"\n", " )\n", "\n", "client = PCSWMMClient(pcpy)\n", "\n", "# Verify that the v0.2 services are present before proceeding.\n", "required_services = [\n", " \"objects\",\n", " \"topology\",\n", " \"engineering\",\n", " \"result_queries\",\n", "]\n", "missing_services = [\n", " name for name in required_services if not hasattr(client, name)\n", "]\n", "\n", "if missing_services:\n", " raise RuntimeError(\n", " \"The selected SDK does not contain the v0.2 services: \"\n", " + \", \".join(missing_services)\n", " )\n", "\n", "client.health()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Project and collection inventory" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "from IPython.display import display, Markdown\n", "display(pd.DataFrame(list(client.project.summary().items()),columns=[\"Property\",\"Value\"]))\n", "display(pd.DataFrame(client.collections.summary()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Object tables" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for name in [\"Nodes\",\"Links\",\"Subcatchments\",\"Storages\",\"Outfalls\",\"Conduits\"]:\n", " display(Markdown(\"### \"+name))\n", " display(pd.DataFrame(client.objects.collection_records(name)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. GIS layers" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "layer_names=client.layers.names()\n", "display(pd.DataFrame({\"Layer\":layer_names}))\n", "if \"Subcatchments\" in layer_names:\n", " display(pd.DataFrame(client.layers.records(\"Subcatchments\")))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Topology screening" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "display(Markdown(\"### Link endpoints\"))\n", "display(pd.DataFrame(client.topology.link_endpoints()))\n", "display(Markdown(\"### Orphan links\"))\n", "display(pd.DataFrame(client.topology.orphan_links()))\n", "display(Markdown(\"### Isolated nodes\"))\n", "display(pd.DataFrame(client.topology.isolated_nodes()))\n", "display(Markdown(\"### Duplicate directed link pairs\"))\n", "display(pd.DataFrame(client.topology.duplicate_link_pairs()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6. Engineering screening" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "display(pd.DataFrame(list(client.engineering.model_screening_summary().items()),columns=[\"Check\",\"Finding count\"]))\n", "display(Markdown(\"### Conduit findings\"))\n", "display(pd.DataFrame(client.engineering.conduit_screening()))\n", "display(Markdown(\"### Subcatchment findings\"))\n", "display(pd.DataFrame(client.engineering.subcatchment_screening()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. Run simulation (explicit)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Uncomment to run:\n", "# display(pd.DataFrame([client.simulation.run()]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 8. Peak flow query" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Uncomment after confirming units and result availability:\n", "# peaks=pd.DataFrame(client.result_queries.peak_for_objects(\"Links\",\"Flow\",\"CMS\",client.collections.keys(\"Links\")))\n", "# display(peaks.sort_values(\"maximum\",ascending=False))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 9. Controlled commands" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def execute_command(command):\n", " c=command.strip().lower()\n", " if c==\"project summary\": return pd.DataFrame(list(client.project.summary().items()),columns=[\"Property\",\"Value\"])\n", " if c==\"model inventory\": return pd.DataFrame(client.collections.summary())\n", " if c==\"list nodes\": return pd.DataFrame({\"Node\":client.collections.keys(\"Nodes\")})\n", " if c==\"list links\": return pd.DataFrame({\"Link\":client.collections.keys(\"Links\")})\n", " if c==\"topology review\": return {\"orphan_links\":client.topology.orphan_links(),\"isolated_nodes\":client.topology.isolated_nodes(),\"duplicate_link_pairs\":client.topology.duplicate_link_pairs()}\n", " if c==\"engineering review\": return client.engineering.model_screening_summary()\n", " mapping={\"show nodes\":\"Nodes\",\"show links\":\"Links\",\"show subcatchments\":\"Subcatchments\",\"show storages\":\"Storages\",\"show outfalls\":\"Outfalls\"}\n", " if c in mapping: return pd.DataFrame(client.objects.collection_records(mapping[c]))\n", " return {\"error\":\"Unsupported command\",\"supported\":[\"project summary\",\"model inventory\",\"list nodes\",\"list links\",\"show nodes\",\"show links\",\"show subcatchments\",\"show storages\",\"show outfalls\",\"topology review\",\"engineering review\"]}\n", "# execute_command(\"engineering review\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Screening results identify conditions for engineering review; they do not independently establish municipal non-compliance." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.10" } }, "nbformat": 4, "nbformat_minor": 5 }