An interactive, proof-of-concept visualization of the CalSim3 water network schematic for the COEQWAL project. It renders the nodes (reservoirs, junctions, demand units, treatment plants, etc.) and arcs (channels, canals, deliveries, returns) of California's water system, with zoom, search, tooltips, and upstream/downstream highlighting.
Built with Vite and D3 v7. No framework.
See what is upstream and downstream:
The project ships three independent pages. Each is a separate Vite entry point that loads one ES module.
| Page | Module | Data source | Status |
|---|---|---|---|
index.html |
networkDiagram.js |
Static public/data/json/networkSchematic.json |
Working Uses layout coordinates from the CalSim diagram. |
index-api.html |
networkDiagramAPI.js |
COEQWAL database API | Prototype. Needs an adapter (see Connecting to the COEQWAL API). |
index-map.html |
mapNetworkDiagram.js |
COEQWAL database API | Prototype. Plots nodes geographically by lat/lon. |
The two API views were written against earlier API endpoints and do not work against the current COEQWAL API without changes.
Requires Node 22 (see .nvmrc).
nvm use # selects Node 22
npm install
npm run dev # starts Vite on http://localhost:3000npm run dev opens the static schematic (index.html). The other views are at http://localhost:3000/index-api.html and http://localhost:3000/index-map.html, but they require a running backend (see below).
npm run build # outputs to dist/
npm run preview # serves the production build locallyNote: vite.config.js only lists index.html as a build input, so npm run build bundles only the static schematic. The API/map pages are dev-only unless added to rollupOptions.input.
networkDiagram.jsfetchespublic/data/json/networkSchematic.json.- It reads
Diagram.Nodes[0].NodeandDiagram.Links[0].Link. - Each node's
Bounds("x,y,width,height") becomes an absolute SVG position. Link ARGB colors are converted to RGBA. - D3 renders an SVG with shapes per
Shape.Id(ellipse, triangle, cylinder, rectangle), plus zoom, a search box, hover tooltips, and upstream/downstream highlighting.
This is the only view that reproduces the true CalSim schematic layout, because those layout coordinates live only in the source diagram, not in the database.
The schematic data originates as a CalSim3 diagram XML and is converted to JSON offline. These are one-off/maintenance scripts, not part of the running app.
| Script | Purpose |
|---|---|
convertXmlToJson.js |
Converts data/xml/CS3_NetworkSchematic_Integrated_11.28.23.xml (UTF-16BE) to data/json/networkSchematic.json. |
generateCSV.js + exportData.js |
Reads the schematic JSON and writes data/nodes_data.csv and data/links_data.csv. |
Note:
convertXmlToJson.jsuses CommonJSrequire()while the package is ESM ("type": "module"), and it reads/writes./data/...rather than./public/data/.... It needs a small update before it will run again.
Standalone Python helpers used during data exploration:
find_inflows.py- maps reservoir codes indata/storage.txtto schematic node IDs (writesoutput.txt).seek_upstream.py- finds all upstream nodes for each reservoir (writesupstream_output.txt).
data/node_types.csv and data/arc_types.csv are reference tables (sourced from the COEQWAL geopackage) describing every node/arc type code, e.g. STR = storage/reservoir, JUNC = junction, CH-CNL = canal, WTP = water treatment plant. Nothing reads these CSVs at runtime; they serve as documentation. The static view colors elements by diagram shape (Shape.Id), and the API prototypes color by numeric type ID, neither consults these tables.
The API views target the coeqwal-data-platform API (api.coeqwal.org, or localhost:8000 locally). The data exists, but the current frontend does not match the current API endpoints.
Differences that must be reconciled before the API views work:
- Endpoints: the frontend calls
/network_node//network_arc. The API serves/api/nodes//api/arcs. (Adjustable at runtime in theindex-api.htmlconfig panel.) - Visibility filter: the frontend requires
integration_status === 'active', a field the API does not return, so every node/arc is filtered out. Map this to the database'soperational_statusor remove the filter. - Geometry: the API returns a parsed
geojsonobject plus top-levellatitude/longitude. The frontend reads ageomstring. The map view should readlatitude/longitudeorgeojson. - Layout: the schematic view relies on
diagram_idfor fallback positioning, which the API does not provide. The database has geographic geometry but not the schematic canvas layout, so the API can drive a geographic map but cannot reproduce the hand-laid schematic. - Types: the API returns type names (
node_type,arc_type) and node short codes forfrom_node/to_node, rather than the numeric IDs the frontend expects.
In short: the map view is achievable with a modestly-easy adapter. The schematic view cannot be faithfully reproduced from the API because the layout data is not in the database.
