From fa57bc701b85e51efdb21ae32a1fb843653f2ad6 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 11:07:57 -0400 Subject: [PATCH 01/12] added Roadmap --- docs/index.rst | 74 +++++++++++--------------------------------------- 1 file changed, 16 insertions(+), 58 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index eba99b0c..f44b8bb0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -20,26 +20,6 @@ An interactive visual tool for modeling and simulating nuclear fuel cycle compon :alt: Node.js 18+ -=============================== -Statement of Need -=============================== - -System modeling is a critical aspect of nuclear engineering that requires sophisticated tools to analyze material flows, reactor performance, and waste management strategies. PathView addresses the need for: - -**Accessibility** - Traditional system simulation tools are often complex, proprietary, or require extensive training. This tool provides an intuitive visual interface that makes system modeling accessible to students, researchers, and professionals. - -**Interactivity** - Static models and command-line tools limit exploration and understanding. Our interactive visual approach allows users to build, modify, and experiment with system scenarios in real-time. - -**Educational Value** - The visual nature of the tool makes it ideal for teaching system concepts, allowing students to see the connections between different components and understand material flows. - -**Research Flexibility** - Researchers need tools that can be easily modified and extended. The open-source nature and modular architecture enable customization for specific research needs. - -**Modern Technology Stack** - Built with modern web technologies (React, Python) that ensure maintainability, extensibility, and cross-platform compatibility. =============================== Installation Guide @@ -56,10 +36,6 @@ Before installing PathView, ensure your system meets the following requirements: - pip for Python package management - Git (for development) -**Supported Operating Systems:** - - Linux (Ubuntu 20.04+, CentOS 8+) - - macOS 10.15+ - - Windows 10+ Installation Steps ------------------ @@ -92,7 +68,15 @@ Installation Steps # On Windows: venv\Scripts\activate + + Alternatively, you can use Conda: + .. code-block:: bash + conda create -n pathview python=3.8 + conda activate pathview + pip install --upgrade pip + pip install -e . + 4. **Install Backend Dependencies** .. code-block:: bash @@ -110,57 +94,31 @@ Installation Steps - Frontend: http://localhost:5173 - Backend API: http://localhost:8000 -Troubleshooting ---------------- - -**Common Issues:** - -- **Node.js version conflicts**: Use nvm to manage Node.js versions -- **Python path issues**: Ensure Python 3.8+ is in your PATH -- **Port conflicts**: Check if ports 5173 or 8000 are already in use -- **Permission errors**: Use appropriate permissions for installation directories - =============================== Example Usage =============================== -Quick Start Example -------------------- - Here's a simple example to get you started with PathView: WIP -Use Cases ---------- - -**Educational Scenarios** - - Simple fuel cycle for classroom demonstrations - - Impact of tritium breeding ratio for fusion reactors - -**Research Applications** - - Advanced reactor fuel cycle analysis - - Multi-recycling scenarios - - Waste minimization strategies - -**Planning and Analysis** - - Regional fuel cycle infrastructure planning - - Economic optimization studies - - Material flow tracking - =============================== Roadmap =============================== -WIP +- Export graph as Subsystem and load it back +- User-defined block class +- Support for user plugins (eg. fuel cycle, thermodynamic models, etc.) +- Enhanced visualization options +- More example scenarios +- Annotations and comments on graph +- More styling options for nodes and edges =============================== Community Guidelines =============================== -Welcome to the PathView community! We're committed to fostering an inclusive, collaborative environment for all contributors. - Code of Conduct ---------------- @@ -171,7 +129,7 @@ Contributing Guidelines **Getting Started** 1. Fork the repository - 2. Create a feature branch (``git checkout -b feature/awesome-feature``) + 2. Create a feature branch (``git checkout -b awesome-feature``) 3. Make your changes 4. Add tests for new functionality if needed 5. Ensure all tests pass From 86f4dc85a8977b7fefc8c17bfbd31ac2dde0e21f Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 11:08:39 -0400 Subject: [PATCH 02/12] solvers --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index f44b8bb0..8683b92a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -107,6 +107,7 @@ WIP Roadmap =============================== +- Support more PathSim solvers - Export graph as Subsystem and load it back - User-defined block class - Support for user plugins (eg. fuel cycle, thermodynamic models, etc.) From b7570c51a76aa7ce961bf2ccb6014c268665f963 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 11:20:00 -0400 Subject: [PATCH 03/12] improved UI/UX --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index 8683b92a..25b4986f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -109,6 +109,7 @@ Roadmap - Support more PathSim solvers - Export graph as Subsystem and load it back +- Improved UI/UX - User-defined block class - Support for user plugins (eg. fuel cycle, thermodynamic models, etc.) - Enhanced visualization options From b4cb9f287a7b5fc30e6cbfca848c48738bcb9797 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 11:21:33 -0400 Subject: [PATCH 04/12] into categories --- docs/index.rst | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 25b4986f..b64fe093 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -107,15 +107,23 @@ WIP Roadmap =============================== -- Support more PathSim solvers -- Export graph as Subsystem and load it back -- Improved UI/UX -- User-defined block class -- Support for user plugins (eg. fuel cycle, thermodynamic models, etc.) -- Enhanced visualization options -- More example scenarios -- Annotations and comments on graph -- More styling options for nodes and edges +**Core Functionality & Solvers** + - Support more PathSim solvers + - User-defined block class + - Support for user plugins (eg. fuel cycle, thermodynamic models, etc.) + +**Graph Management & Import/Export** + - Export graph as Subsystem and load it back + +**User Interface & Experience** + - Improved UI/UX + - Capability to rotate/flip nodes + - Enhanced visualization options + - More styling options for nodes and edges + +**Documentation & Examples** + - More example scenarios + - Annotations and comments on graph =============================== Community Guidelines From 3e0186ca26d00d7cc3359da527f92a68ee37895f Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 16:33:40 -0400 Subject: [PATCH 05/12] added example usage --- docs/index.rst | 38 +- example_graphs/baby.json | 804 ---------------------------- example_graphs/events.json | 140 ----- example_graphs/events_advanced.json | 365 ------------- 4 files changed, 35 insertions(+), 1312 deletions(-) delete mode 100644 example_graphs/baby.json delete mode 100644 example_graphs/events.json delete mode 100644 example_graphs/events_advanced.json diff --git a/docs/index.rst b/docs/index.rst index b64fe093..7be6bb99 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -100,7 +100,39 @@ Example Usage Here's a simple example to get you started with PathView: -WIP +1. **Start the Application** + + After installation, launch PathView: + + .. code-block:: bash + + npm run start:both + + Navigate to http://localhost:5173 in your browser. + +2. **Load Example Files** + + PathView includes several pre-built example graphs in the `example_graphs/ `_ directory that demonstrate different functionality: + + - ``harmonic_oscillator.json`` - Simple oscillator simulation + - ``pid.json`` - PID controller example + - ``festim_two_walls.json`` - Two-wall diffusion model + - ``linear_feedback.json`` - Linear feedback system + - ``spectrum.json`` - Spectral analysis example + + To load an example: + + - Use the file import functionality in the application + - Select any ``.json`` file from the ``example_graphs/`` directory + - The graph will load with pre-configured nodes and connections + - Click the Run button to run the example + +3. **Create Your Own Graphs** + + - Drag and drop nodes from the sidebar + - Connect nodes by dragging from output handles to input handles + - Configure node parameters in the properties panel + - Use the simulation controls to run your model =============================== @@ -109,8 +141,8 @@ Roadmap **Core Functionality & Solvers** - Support more PathSim solvers - - User-defined block class - - Support for user plugins (eg. fuel cycle, thermodynamic models, etc.) + - User-defined block class (ie. users writing their own Python classes for blocks) + - Support for user plugins (eg. Chem.Eng., fuel cycle blocks, thermodynamic models, etc.) **Graph Management & Import/Export** - Export graph as Subsystem and load it back diff --git a/example_graphs/baby.json b/example_graphs/baby.json deleted file mode 100644 index 4287de6d..00000000 --- a/example_graphs/baby.json +++ /dev/null @@ -1,804 +0,0 @@ -{ - "nodes": [ - { - "data": { - "gain": "-1", - "label": "x (-1)" - }, - "dragging": false, - "id": "4", - "measured": { - "height": 80, - "width": 90 - }, - "position": { - "x": 508, - "y": 369 - }, - "selected": false, - "type": "amplifier" - }, - { - "data": { - "label": "Neutron rate", - "labels": "", - "sampling_rate": "", - "t_wait": "" - }, - "dragging": false, - "id": "6", - "measured": { - "height": 64, - "width": 64 - }, - "position": { - "x": 738, - "y": 385 - }, - "selected": false, - "type": "adder" - }, - { - "data": { - "gain": "3e-3", - "label": "TBR" - }, - "dragging": false, - "id": "7", - "measured": { - "height": 80, - "width": 90 - }, - "position": { - "x": 912, - "y": 486 - }, - "selected": false, - "type": "amplifier" - }, - { - "data": { - "initial_value": "", - "label": "BABY", - "residence_time": "(k_IV + k_OV)/baby_vol", - "source_term": "" - }, - "dragging": false, - "id": "8", - "measured": { - "height": 120, - "width": 200 - }, - "position": { - "x": 1020.1905095320806, - "y": 573.6390158215457 - }, - "selected": false, - "type": "process" - }, - { - "data": { - "label": "IV vial activity", - "labels": "", - "sampling_rate": "", - "t_wait": "" - }, - "dragging": false, - "id": "21", - "measured": { - "height": 140, - "width": 120 - }, - "position": { - "x": 1949.5229665105167, - "y": 563.941606900507 - }, - "selected": false, - "type": "scope" - }, - { - "data": { - "f1": "0.01", - "f2": "0.99", - "label": "soluble vs insoluble" - }, - "dragging": false, - "id": "1", - "measured": { - "height": 120, - "width": 120 - }, - "position": { - "x": 1394.0782538373574, - "y": 743.9802025169162 - }, - "selected": false, - "type": "splitter2" - }, - { - "id": "23", - "type": "bubbler", - "position": { - "x": 1595, - "y": 722 - }, - "data": { - "label": "IV bubbler", - "conversion_efficiency": "0.95", - "vial_efficiency": "0.9", - "replacement_times": "np.arange(5, 50, step=3)" - }, - "measured": { - "width": 230, - "height": 160 - }, - "selected": false, - "dragging": false - }, - { - "id": "24", - "type": "splitter2", - "position": { - "x": 1193, - "y": 851 - }, - "data": { - "label": "IV vs OV", - "f1": "k_IV/(k_IV + k_OV)", - "f2": "k_OV/(k_IV + k_OV)" - }, - "measured": { - "width": 120, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "25", - "type": "splitter2", - "position": { - "x": 1410.747877541758, - "y": 965.2139451372932 - }, - "data": { - "label": "soluble vs insoluble", - "f1": "0.01", - "f2": "0.99" - }, - "measured": { - "width": 120, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "26", - "type": "bubbler", - "position": { - "x": 1602.4670834180595, - "y": 970.2206053879095 - }, - "data": { - "label": "OV bubbler", - "conversion_efficiency": "0.95", - "vial_efficiency": "0.9", - "replacement_times": "np.arange(5, 50, step=5)" - }, - "measured": { - "width": 230, - "height": 160 - }, - "selected": false, - "dragging": false - }, - { - "id": "27", - "type": "integrator", - "position": { - "x": 2059.579367811878, - "y": 919.8031067000171 - }, - "data": { - "label": "environment", - "initial_value": "", - "reset_times": "" - }, - "measured": { - "width": 200, - "height": 48 - }, - "selected": false, - "dragging": false - }, - { - "id": "28", - "type": "scope", - "position": { - "x": 1923.4902343023584, - "y": 1097.1334152526842 - }, - "data": { - "label": "OV vial activity", - "labels": "", - "sampling_rate": "", - "t_wait": "" - }, - "measured": { - "width": 120, - "height": 140 - }, - "selected": false, - "dragging": false - }, - { - "id": "30", - "type": "scope", - "position": { - "x": 916, - "y": 786 - }, - "data": { - "label": "BABY inventory", - "labels": "", - "sampling_rate": "", - "t_wait": "" - }, - "measured": { - "width": 120, - "height": 140 - }, - "selected": false, - "dragging": false - }, - { - "id": "31", - "type": "stepsource", - "position": { - "x": 435.96282260684967, - "y": 213.2008701092014 - }, - "data": { - "label": "Stepsource", - "amplitude": "1", - "tau": "4" - }, - "measured": { - "width": 120, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "32", - "type": "stepsource", - "position": { - "x": 324.7489008596274, - "y": 356.4037177393149 - }, - "data": { - "label": "Stepsource", - "amplitude": "1", - "tau": "2" - }, - "measured": { - "width": 120, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "33", - "type": "scope", - "position": { - "x": 889.5927227230428, - "y": 175.9984179832702 - }, - "data": { - "label": "Neutron source", - "labels": "", - "sampling_rate": "", - "t_wait": "" - }, - "measured": { - "width": 120, - "height": 140 - }, - "selected": true, - "dragging": false - } - ], - "edges": [ - { - "data": {}, - "id": "e4-6", - "markerEnd": { - "color": "#ECDFCC", - "height": 20, - "type": "arrowclosed", - "width": 20 - }, - "source": "4", - "sourceHandle": null, - "style": { - "stroke": "#ECDFCC", - "strokeWidth": 2 - }, - "target": "6", - "targetHandle": null, - "type": "smoothstep" - }, - { - "data": {}, - "id": "e6-7", - "markerEnd": { - "color": "#ECDFCC", - "height": 20, - "type": "arrowclosed", - "width": 20 - }, - "source": "6", - "sourceHandle": null, - "style": { - "stroke": "#ECDFCC", - "strokeWidth": 2 - }, - "target": "7", - "targetHandle": null, - "type": "smoothstep" - }, - { - "data": {}, - "id": "e7-8", - "markerEnd": { - "color": "#ECDFCC", - "height": 20, - "type": "arrowclosed", - "width": 20 - }, - "source": "7", - "sourceHandle": null, - "style": { - "stroke": "#ECDFCC", - "strokeWidth": 2 - }, - "target": "8", - "targetHandle": null, - "type": "smoothstep" - }, - { - "id": "e24-1-from_source1", - "source": "24", - "target": "1", - "sourceHandle": "source1", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e1-23-from_source1-to_sample_in_soluble", - "source": "1", - "target": "23", - "sourceHandle": "source1", - "targetHandle": "sample_in_soluble", - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e1-23-from_source2-to_sample_in_insoluble", - "source": "1", - "target": "23", - "sourceHandle": "source2", - "targetHandle": "sample_in_insoluble", - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-21-from_vial1", - "source": "23", - "target": "21", - "sourceHandle": "vial1", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-21-from_vial2", - "source": "23", - "target": "21", - "sourceHandle": "vial2", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-21-from_vial3", - "source": "23", - "target": "21", - "sourceHandle": "vial3", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-21-from_vial4", - "source": "23", - "target": "21", - "sourceHandle": "vial4", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e8-24-from_mass_flow_rate", - "source": "8", - "target": "24", - "sourceHandle": "mass_flow_rate", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e24-25-from_source2", - "source": "24", - "target": "25", - "sourceHandle": "source2", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e25-26-from_source1-to_sample_in_soluble", - "source": "25", - "target": "26", - "sourceHandle": "source1", - "targetHandle": "sample_in_soluble", - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e25-26-from_source2-to_sample_in_insoluble", - "source": "25", - "target": "26", - "sourceHandle": "source2", - "targetHandle": "sample_in_insoluble", - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-27-from_sample_out", - "source": "23", - "target": "27", - "sourceHandle": "sample_out", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-27-from_sample_out", - "source": "26", - "target": "27", - "sourceHandle": "sample_out", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-28-from_vial1", - "source": "26", - "target": "28", - "sourceHandle": "vial1", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-28-from_vial2", - "source": "26", - "target": "28", - "sourceHandle": "vial2", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-28-from_vial3", - "source": "26", - "target": "28", - "sourceHandle": "vial3", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-28-from_vial4", - "source": "26", - "target": "28", - "sourceHandle": "vial4", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e8-30-from_inv", - "source": "8", - "target": "30", - "sourceHandle": "inv", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e31-4", - "source": "31", - "target": "4", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e32-6", - "source": "32", - "target": "6", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e6-33", - "source": "6", - "target": "33", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - } - ], - "nodeCounter": 34, - "solverParams": { - "dt": "0.01", - "dt_min": "1e-6", - "dt_max": "1.0", - "Solver": "SSPRK22", - "tolerance_fpi": "1e-6", - "iterations_max": "100", - "log": "true", - "simulation_duration": "50.0", - "extra_params": "{\"tolerance_lte_rel\":1e-4, \"tolerance_lte_abs\":1e-9}" - }, - "globalVariables": [ - { - "id": "1753792090540", - "name": "baby_vol", - "value": "1", - "nameError": false - }, - { - "id": "1753797344108", - "name": "k_IV", - "value": "5", - "nameError": false - }, - { - "id": "1753797380350", - "name": "k_OV", - "value": "1", - "nameError": false - } - ] -} \ No newline at end of file diff --git a/example_graphs/events.json b/example_graphs/events.json deleted file mode 100644 index 47c11737..00000000 --- a/example_graphs/events.json +++ /dev/null @@ -1,140 +0,0 @@ -{ - "nodes": [ - { - "id": "0", - "type": "constant", - "position": { - "x": 443.74999237060547, - "y": 132.24999809265137 - }, - "data": { - "label": "source", - "value": "" - }, - "measured": { - "width": 205, - "height": 53 - }, - "selected": true - }, - { - "id": "1", - "type": "integrator", - "position": { - "x": 688.7499923706055, - "y": 251.24999809265137 - }, - "data": { - "label": "integrator", - "initial_value": "", - "reset_times": "" - }, - "measured": { - "width": 200, - "height": 48 - }, - "selected": false, - "dragging": false - }, - { - "id": "2", - "type": "scope", - "position": { - "x": 1022.2499923706055, - "y": 252.24999809265137 - }, - "data": { - "label": "scope 2", - "labels": "", - "sampling_rate": "", - "t_wait": "" - }, - "measured": { - "width": 120, - "height": 140 - } - } - ], - "edges": [ - { - "id": "e0-1", - "source": "0", - "target": "1", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e0-2", - "source": "0", - "target": "2", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e1-2", - "source": "1", - "target": "2", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - } - ], - "nodeCounter": 3, - "solverParams": { - "dt": "0.01", - "dt_min": "1e-6", - "dt_max": "1.0", - "Solver": "SSPRK22", - "tolerance_fpi": "1e-6", - "iterations_max": "100", - "log": "true", - "simulation_duration": "50.0", - "extra_params": "{}" - }, - "globalVariables": [], - "events": [ - { - "name": "my_event", - "type": "ZeroCrossingDown", - "func_evt": "def func_evt(t):\n *_, x = integrator_1()\n return 10 - x", - "func_act": "def func_act(t):\n source_0.off()", - "tolerance": "1e-8", - "id": 1754342253698 - } - ] -} \ No newline at end of file diff --git a/example_graphs/events_advanced.json b/example_graphs/events_advanced.json deleted file mode 100644 index e642150a..00000000 --- a/example_graphs/events_advanced.json +++ /dev/null @@ -1,365 +0,0 @@ -{ - "nodes": [ - { - "id": "2", - "type": "process", - "position": { - "x": 868.2944372219196, - "y": 463.7056320088598 - }, - "data": { - "label": "process 2", - "initial_value": "", - "residence_time": "30", - "source_term": "" - }, - "measured": { - "width": 200, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "5", - "type": "amplifier", - "position": { - "x": 324.22187866193707, - "y": 500.1415773669528 - }, - "data": { - "label": "amplifier 5", - "gain": "-1" - }, - "measured": { - "width": 90, - "height": 80 - }, - "selected": false, - "dragging": false - }, - { - "id": "6", - "type": "scope", - "position": { - "x": 849.5352656218994, - "y": 616.3744300730544 - }, - "data": { - "label": "scope 6", - "labels": "", - "sampling_rate": "", - "t_wait": "" - }, - "measured": { - "width": 120, - "height": 140 - }, - "selected": false, - "dragging": false - }, - { - "id": "7", - "type": "scope", - "position": { - "x": 884.3339278689236, - "y": 272.62551973484125 - }, - "data": { - "label": "scope 7", - "labels": "", - "sampling_rate": "", - "t_wait": "" - }, - "measured": { - "width": 120, - "height": 140 - }, - "selected": false, - "dragging": false - }, - { - "id": "8", - "type": "adder", - "position": { - "x": 470.494411363933, - "y": 507.51391609780273 - }, - "data": { - "label": "adder 8", - "operations": "" - }, - "measured": { - "width": 64, - "height": 64 - }, - "selected": false, - "dragging": false - }, - { - "id": "9", - "type": "integrator", - "position": { - "x": 600.7345026088365, - "y": 514.5712609435857 - }, - "data": { - "label": "storage", - "initial_value": "startup_inv", - "reset_times": "" - }, - "measured": { - "width": 200, - "height": 48 - }, - "selected": false, - "dragging": false - }, - { - "id": "10", - "type": "pulsesource", - "position": { - "x": 533.6515111182074, - "y": 340.6779400691841 - }, - "data": { - "label": "fusion rate", - "T": "", - "amplitude": "", - "duty": "", - "t_fall": "", - "t_rise": "", - "tau": "" - }, - "measured": { - "width": 205, - "height": 53 - }, - "selected": true, - "dragging": false - }, - { - "id": "12", - "type": "amplifier", - "position": { - "x": 734.4442527405984, - "y": 407.0512209610127 - }, - "data": { - "label": "amplifier 12", - "gain": "1.1" - }, - "measured": { - "width": 90, - "height": 80 - }, - "selected": false, - "dragging": false - } - ], - "edges": [ - { - "id": "e2-6-from_inv", - "source": "2", - "target": "6", - "sourceHandle": "inv", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e5-8", - "source": "5", - "target": "8", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e2-8-from_mass_flow_rate", - "source": "2", - "target": "8", - "sourceHandle": "mass_flow_rate", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e8-9", - "source": "8", - "target": "9", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e9-6", - "source": "9", - "target": "6", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e10-5", - "source": "10", - "target": "5", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e10-7", - "source": "10", - "target": "7", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e10-12", - "source": "10", - "target": "12", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e12-2", - "source": "12", - "target": "2", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - } - ], - "nodeCounter": 13, - "solverParams": { - "dt": "0.01", - "dt_min": "1e-6", - "dt_max": "1.0", - "Solver": "SSPRK22", - "tolerance_fpi": "1e-6", - "iterations_max": "100", - "log": "true", - "simulation_duration": "300", - "extra_params": "{}" - }, - "globalVariables": [], - "events": [ - { - "name": "storage_empty", - "type": "ZeroCrossingDown", - "func_evt": "fun_stor_evt", - "func_act": "fun_stor_act", - "tolerance": "1e-8", - "id": 1754440495739 - }, - { - "name": "restart", - "type": "ZeroCrossingUp", - "func_evt": "func_evt_start", - "func_act": "func_act_start", - "tolerance": "1e-8", - "id": 1754440898819 - } - ], - "pythonCode": "def fun_stor_evt(t):\n *_, I = storage_9()\n return I\n\ndef fun_stor_act(t):\n fusion_rate_10.off()\n\nstartup_inv = 10\n\ndef func_evt_start(t):\n *_, I = storage_9()\n return I - startup_inv\n\ndef func_act_start(t):\n fusion_rate_10.on()\n " -} \ No newline at end of file From de59bb9233188508cb58a79bd67dec403a89f11e Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 16:35:03 -0400 Subject: [PATCH 06/12] removed example --- example_graphs/baby.json | 826 --------------------------------------- 1 file changed, 826 deletions(-) delete mode 100644 example_graphs/baby.json diff --git a/example_graphs/baby.json b/example_graphs/baby.json deleted file mode 100644 index f9377337..00000000 --- a/example_graphs/baby.json +++ /dev/null @@ -1,826 +0,0 @@ -{ - "version": { - "pathsim_version": "0.8.2", - "pathview_version": "0.1.dev470+g017515800.d20250812" - }, - "nodes": [ - { - "data": { - "gain": "-1", - "label": "x (-1)", - "nodeColor": "#DDE6ED" - }, - "dragging": false, - "id": "4", - "measured": { - "height": 80, - "width": 90 - }, - "position": { - "x": 508, - "y": 369 - }, - "selected": false, - "type": "amplifier" - }, - { - "data": { - "label": "Neutron rate", - "labels": "", - "sampling_rate": "", - "t_wait": "", - "nodeColor": "#DDE6ED" - }, - "dragging": false, - "id": "6", - "measured": { - "height": 64, - "width": 64 - }, - "position": { - "x": 738, - "y": 385 - }, - "selected": false, - "type": "adder" - }, - { - "data": { - "gain": "3e-3", - "label": "TBR", - "nodeColor": "#DDE6ED" - }, - "dragging": false, - "id": "7", - "measured": { - "height": 80, - "width": 90 - }, - "position": { - "x": 912, - "y": 486 - }, - "selected": false, - "type": "amplifier" - }, - { - "data": { - "initial_value": "", - "label": "BABY", - "residence_time": "(k_IV + k_OV)/baby_vol", - "source_term": "", - "nodeColor": "#DDE6ED" - }, - "dragging": false, - "id": "8", - "measured": { - "height": 120, - "width": 200 - }, - "position": { - "x": 1020.1905095320806, - "y": 573.6390158215457 - }, - "selected": false, - "type": "process" - }, - { - "data": { - "label": "IV vial activity", - "labels": "", - "sampling_rate": "", - "t_wait": "", - "nodeColor": "#DDE6ED" - }, - "dragging": false, - "id": "21", - "measured": { - "height": 140, - "width": 120 - }, - "position": { - "x": 1949.5229665105167, - "y": 563.941606900507 - }, - "selected": false, - "type": "scope" - }, - { - "data": { - "f1": "0.01", - "f2": "0.99", - "label": "soluble vs insoluble", - "nodeColor": "#DDE6ED" - }, - "dragging": false, - "id": "1", - "measured": { - "height": 120, - "width": 120 - }, - "position": { - "x": 1394.0782538373574, - "y": 743.9802025169162 - }, - "selected": false, - "type": "splitter2" - }, - { - "id": "23", - "type": "bubbler", - "position": { - "x": 1595, - "y": 722 - }, - "data": { - "label": "IV bubbler", - "conversion_efficiency": "0.95", - "vial_efficiency": "0.9", - "replacement_times": "np.arange(5, 50, step=3)", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 230, - "height": 160 - }, - "selected": false, - "dragging": false - }, - { - "id": "24", - "type": "splitter2", - "position": { - "x": 1193, - "y": 851 - }, - "data": { - "label": "IV vs OV", - "f1": "k_IV/(k_IV + k_OV)", - "f2": "k_OV/(k_IV + k_OV)", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 120, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "25", - "type": "splitter2", - "position": { - "x": 1410.747877541758, - "y": 965.2139451372932 - }, - "data": { - "label": "soluble vs insoluble", - "f1": "0.01", - "f2": "0.99", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 120, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "26", - "type": "bubbler", - "position": { - "x": 1602.4670834180595, - "y": 970.2206053879095 - }, - "data": { - "label": "OV bubbler", - "conversion_efficiency": "0.95", - "vial_efficiency": "0.9", - "replacement_times": "np.arange(5, 50, step=5)", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 230, - "height": 160 - }, - "selected": false, - "dragging": false - }, - { - "id": "27", - "type": "integrator", - "position": { - "x": 2059.579367811878, - "y": 919.8031067000171 - }, - "data": { - "label": "environment", - "initial_value": "", - "reset_times": "", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 200, - "height": 48 - }, - "selected": false, - "dragging": false - }, - { - "id": "28", - "type": "scope", - "position": { - "x": 1923.4902343023584, - "y": 1097.1334152526842 - }, - "data": { - "label": "OV vial activity", - "labels": "", - "sampling_rate": "", - "t_wait": "", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 120, - "height": 140 - }, - "selected": false, - "dragging": false - }, - { - "id": "30", - "type": "scope", - "position": { - "x": 916, - "y": 786 - }, - "data": { - "label": "BABY inventory", - "labels": "", - "sampling_rate": "", - "t_wait": "", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 120, - "height": 140 - }, - "selected": false, - "dragging": false - }, - { - "id": "31", - "type": "stepsource", - "position": { - "x": 435.96282260684967, - "y": 213.2008701092014 - }, - "data": { - "label": "Stepsource", - "amplitude": "1", - "tau": "4", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 120, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "32", - "type": "stepsource", - "position": { - "x": 324.7489008596274, - "y": 356.4037177393149 - }, - "data": { - "label": "Stepsource", - "amplitude": "1", - "tau": "2", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 120, - "height": 120 - }, - "selected": false, - "dragging": false - }, - { - "id": "33", - "type": "scope", - "position": { - "x": 889.5927227230428, - "y": 175.9984179832702 - }, - "data": { - "label": "Neutron source", - "labels": "", - "sampling_rate": "", - "t_wait": "", - "nodeColor": "#DDE6ED" - }, - "measured": { - "width": 120, - "height": 140 - }, - "selected": true, - "dragging": false - } - ], - "edges": [ - { - "data": {}, - "id": "e4-6", - "markerEnd": { - "color": "#ECDFCC", - "height": 20, - "type": "arrowclosed", - "width": 20 - }, - "source": "4", - "sourceHandle": null, - "style": { - "stroke": "#ECDFCC", - "strokeWidth": 2 - }, - "target": "6", - "targetHandle": null, - "type": "smoothstep" - }, - { - "data": {}, - "id": "e6-7", - "markerEnd": { - "color": "#ECDFCC", - "height": 20, - "type": "arrowclosed", - "width": 20 - }, - "source": "6", - "sourceHandle": null, - "style": { - "stroke": "#ECDFCC", - "strokeWidth": 2 - }, - "target": "7", - "targetHandle": null, - "type": "smoothstep" - }, - { - "data": {}, - "id": "e7-8", - "markerEnd": { - "color": "#ECDFCC", - "height": 20, - "type": "arrowclosed", - "width": 20 - }, - "source": "7", - "sourceHandle": null, - "style": { - "stroke": "#ECDFCC", - "strokeWidth": 2 - }, - "target": "8", - "targetHandle": null, - "type": "smoothstep" - }, - { - "id": "e24-1-from_source1", - "source": "24", - "target": "1", - "sourceHandle": "source1", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e1-23-from_source1-to_sample_in_soluble", - "source": "1", - "target": "23", - "sourceHandle": "source1", - "targetHandle": "sample_in_soluble", - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e1-23-from_source2-to_sample_in_insoluble", - "source": "1", - "target": "23", - "sourceHandle": "source2", - "targetHandle": "sample_in_insoluble", - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-21-from_vial1", - "source": "23", - "target": "21", - "sourceHandle": "vial1", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-21-from_vial2", - "source": "23", - "target": "21", - "sourceHandle": "vial2", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-21-from_vial3", - "source": "23", - "target": "21", - "sourceHandle": "vial3", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-21-from_vial4", - "source": "23", - "target": "21", - "sourceHandle": "vial4", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e8-24-from_mass_flow_rate", - "source": "8", - "target": "24", - "sourceHandle": "mass_flow_rate", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e24-25-from_source2", - "source": "24", - "target": "25", - "sourceHandle": "source2", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e25-26-from_source1-to_sample_in_soluble", - "source": "25", - "target": "26", - "sourceHandle": "source1", - "targetHandle": "sample_in_soluble", - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e25-26-from_source2-to_sample_in_insoluble", - "source": "25", - "target": "26", - "sourceHandle": "source2", - "targetHandle": "sample_in_insoluble", - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e23-27-from_sample_out", - "source": "23", - "target": "27", - "sourceHandle": "sample_out", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-27-from_sample_out", - "source": "26", - "target": "27", - "sourceHandle": "sample_out", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-28-from_vial1", - "source": "26", - "target": "28", - "sourceHandle": "vial1", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-28-from_vial2", - "source": "26", - "target": "28", - "sourceHandle": "vial2", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-28-from_vial3", - "source": "26", - "target": "28", - "sourceHandle": "vial3", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e26-28-from_vial4", - "source": "26", - "target": "28", - "sourceHandle": "vial4", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e8-30-from_inv", - "source": "8", - "target": "30", - "sourceHandle": "inv", - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e31-4", - "source": "31", - "target": "4", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e32-6", - "source": "32", - "target": "6", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - }, - { - "id": "e6-33", - "source": "6", - "target": "33", - "sourceHandle": null, - "targetHandle": null, - "type": "smoothstep", - "data": {}, - "style": { - "strokeWidth": 2, - "stroke": "#ECDFCC" - }, - "markerEnd": { - "type": "arrowclosed", - "width": 20, - "height": 20, - "color": "#ECDFCC" - } - } - ], - "nodeCounter": 34, - "solverParams": { - "dt": "0.01", - "dt_min": "1e-6", - "dt_max": "1.0", - "Solver": "SSPRK22", - "tolerance_fpi": "1e-6", - "iterations_max": "100", - "log": "true", - "simulation_duration": "50.0", - "extra_params": "{\"tolerance_lte_rel\":1e-4, \"tolerance_lte_abs\":1e-9}" - }, - "globalVariables": [ - { - "id": "1753792090540", - "name": "baby_vol", - "value": "1", - "nameError": false - }, - { - "id": "1753797344108", - "name": "k_IV", - "value": "5", - "nameError": false - }, - { - "id": "1753797380350", - "name": "k_OV", - "value": "1", - "nameError": false - } - ], - "events": [], - "pythonCode": "# Define your Python variables and functions here\n# Example:\n# my_variable = 42\n# def my_function(x):\n# return x * 2\n" -} \ No newline at end of file From dd2eb0ae66d69d9f0fd421e964330cada6cfe563 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 16:40:49 -0400 Subject: [PATCH 07/12] dosctrings --- src/python/custom_pathsim_blocks.py | 69 ++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/src/python/custom_pathsim_blocks.py b/src/python/custom_pathsim_blocks.py index 39b96bc8..17820e39 100644 --- a/src/python/custom_pathsim_blocks.py +++ b/src/python/custom_pathsim_blocks.py @@ -6,6 +6,15 @@ class Process(ODE): + """ + A block that represents a process with a residence time and a source term. + + Args: + residence_time: Residence time of the process. + initial_value: Initial value of the process. + source_term: Source term of the process. + """ + _port_map_out = {"inv": 0, "mass_flow_rate": 1} def __init__(self, residence_time=0, initial_value=0, source_term=0): @@ -33,6 +42,8 @@ def update(self, t): class Splitter(Block): + """Splitter block that splits the input signal into multiple outputs based on specified fractions.""" + def __init__(self, n=2, fractions=None): super().__init__() self.n = n # number of splits @@ -70,7 +81,42 @@ def __init__(self, f1=1 / 3, f2=1 / 3, f3=1 / 3): class Integrator(pathsim.blocks.Integrator): - """Integrator block with a reset method.""" + """Integrates the input signal using a numerical integration engine like this: + + .. math:: + + y(t) = \\int_0^t u(\\tau) \\ d \\tau + + or in differential form like this: + + .. math:: + \\begin{eqnarray} + \\dot{x}(t) &= u(t) \\\\ + y(t) &= x(t) + \\end{eqnarray} + + The Integrator block is inherently MIMO capable, so `u` and `y` can be vectors. + + Example + ------- + This is how to initialize the integrator: + + .. code-block:: python + + #initial value 0.0 + i1 = Integrator() + + #initial value 2.5 + i2 = Integrator(2.5) + + + Parameters + ---------- + initial_value : float, array + initial value of integrator + reset_times : list, optional + List of times at which the integrator is reset. + """ def __init__(self, initial_value=0.0, reset_times=None): """ @@ -112,7 +158,17 @@ def func_act(_): class Bubbler(Subsystem): - """Subsystem representing a tritium bubbling system with 4 vials.""" + """ + Subsystem representing a tritium bubbling system with 4 vials. + + Args: + conversion_efficiency: Conversion efficiency from insoluble to soluble (between 0 and 1). + vial_efficiency: collection efficiency of each vial (between 0 and 1). + replacement_times: List of times at which each vial is replaced. If None, no replacement + events are created. If a single value is provided, it is used for all vials. + If a single list of floats is provided, it will be used for all vials. + If a list of lists is provided, each sublist corresponds to the replacement times for each vial. + """ vial_efficiency: float conversion_efficiency: float @@ -137,15 +193,6 @@ def __init__( vial_efficiency=0.9, replacement_times=None, ): - """ - Args: - conversion_efficiency: Conversion efficiency from insoluble to soluble (between 0 and 1). - vial_efficiency: collection efficiency of each vial (between 0 and 1). - replacement_times: List of times at which each vial is replaced. If None, no replacement - events are created. If a single value is provided, it is used for all vials. - If a single list of floats is provided, it will be used for all vials. - If a list of lists is provided, each sublist corresponds to the replacement times for each vial. - """ self.reset_times = replacement_times self.n_soluble_vials = 2 self.n_insoluble_vials = 2 From d0e595190bf2ee3e919b8978ff4b110662a572fe Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 16:45:38 -0400 Subject: [PATCH 08/12] PathView title --- index.html | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index 0c589ecc..67d4631b 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,16 @@ - - - - - Vite + React - - -
- - - + + + + + + PathView + + + +
+ + + + \ No newline at end of file From 52457f557d2436ee41f3c1ded65174342159de8a Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 16:55:29 -0400 Subject: [PATCH 09/12] docstrings for all functions --- src/python/pathsim_utils.py | 186 +++++++++++++++++++++++++++++++++++- 1 file changed, 182 insertions(+), 4 deletions(-) diff --git a/src/python/pathsim_utils.py b/src/python/pathsim_utils.py index 51b0208c..d4300c71 100644 --- a/src/python/pathsim_utils.py +++ b/src/python/pathsim_utils.py @@ -1,3 +1,22 @@ +""" +Utilities for converting graph-based representations to PathSim simulations. + +This module provides functionality to convert visual graph representations of simulation +models into executable PathSim simulations. It handles the creation of blocks, connections, +events, and solver configurations from JSON-like graph data structures. + +The main workflow involves: +1. Processing global variables and solver parameters +2. Creating blocks from node data +3. Establishing connections between blocks based on edges +4. Setting up events and custom Python code execution +5. Building the complete PathSim simulation model + +Key mappings are provided for: +- Block types (map_str_to_object): Maps string identifiers to PathSim block classes +- Event types (map_str_to_event): Maps string identifiers to PathSim event classes +- Solver types (NAME_TO_SOLVER): Maps string identifiers to PathSim solver classes +""" import math import numpy as np from pathsim import Simulation, Connection @@ -146,14 +165,48 @@ def find_node_by_id(node_id: str, nodes: list[dict]) -> dict: + """ + Find a node by its ID in a list of nodes. + + Args: + node_id: The ID of the node to find. + nodes: A list of node dictionaries to search through. + + Returns: + The node dictionary with the matching ID, or None if not found. + """ return next((node for node in nodes if node["id"] == node_id), None) def find_block_by_id(block_id: str, blocks: list[Block]) -> Block: + """ + Find a block by its ID in a list of blocks. + + Args: + block_id: The ID of the block to find. + blocks: A list of Block objects to search through. + + Returns: + The Block object with the matching ID, or None if not found. + """ return next((block for block in blocks if block.id == block_id), None) def make_global_variables(global_vars): + """ + Validate and execute global variable definitions to make them usable in the simulation. + + Args: + global_vars: A list of dictionaries containing variable definitions, where each + dictionary has 'name' and 'value' keys. + + Returns: + dict: A namespace dictionary containing the global variables. + + Raises: + ValueError: If a variable name is invalid, is a Python keyword, or if there's + an error evaluating the variable value. + """ # Validate and exec global variables so that they are usable later in this script. # Return a namespace dictionary containing the global variables global_namespace = globals().copy() @@ -193,6 +246,23 @@ def make_global_variables(global_vars): def make_solver_params(solver_prms, eval_namespace=None): + """ + Process and validate solver parameters from the graph data. + + Args: + solver_prms: Dictionary containing solver parameters including Solver type, + simulation_duration, and other solver-specific parameters. + eval_namespace: Optional namespace for evaluating parameter expressions. + + Returns: + tuple: A tuple containing: + - solver_prms (dict): Processed solver parameters + - extra_params (dict): Additional parameters for the solver + - duration (float): Simulation duration + + Raises: + ValueError: If invalid parameter values are provided or if solver type is unknown. + """ extra_params = solver_prms.pop("extra_params", "") if extra_params == "": extra_params = {} @@ -295,6 +365,21 @@ def auto_event_construction(event_data: dict, eval_namespace: dict = None) -> Ev def get_parameters_for_event_class( event_class: type, event_data: dict, eval_namespace: dict = None ): + """ + Extract and process parameters for an event class from event data. + + Args: + event_class: The event class type to create parameters for. + event_data: Dictionary containing the event configuration data. + eval_namespace: Optional namespace for evaluating expressions and executing functions. + + Returns: + dict: A dictionary of parameters ready to be passed to the event class constructor. + + Raises: + ValueError: If required parameters are missing, if function code execution fails, + or if parameter evaluation fails. + """ parameters_for_class = inspect.signature(event_class.__init__).parameters # Create a local namespace for executing the event functions @@ -345,6 +430,20 @@ def get_parameters_for_event_class( def get_parameters_for_block_class(block_class, node, eval_namespace): + """ + Extract and process parameters for a block class from node data. + + Args: + block_class: The block class type to create parameters for. + node: Dictionary containing the node configuration data. + eval_namespace: Namespace for evaluating parameter expressions. + + Returns: + dict: A dictionary of parameters ready to be passed to the block class constructor. + + Raises: + ValueError: If required parameters are missing or if parameter evaluation fails. + """ parameters_for_class = inspect.signature(block_class.__init__).parameters parameters = {} for k, value in parameters_for_class.items(): @@ -374,6 +473,18 @@ def get_parameters_for_block_class(block_class, node, eval_namespace): def make_blocks( nodes: list[dict], eval_namespace: dict = None ) -> tuple[list[Block], list[Event]]: + """ + Create Block objects from node data and collect any associated events. + + Args: + nodes: List of node dictionaries containing block configuration data. + eval_namespace: Optional namespace for evaluating expressions. + + Returns: + tuple: A tuple containing: + - blocks (list[Block]): List of created Block objects + - events (list[Event]): List of events created by blocks (e.g., reset events) + """ blocks, events = [], [] for node in nodes: @@ -393,11 +504,16 @@ def get_input_index(block: Block, edge: dict, block_to_input_index: dict) -> int Get the input index for a block based on the edge data. Args: - block: The block object. + block: The block object to get the input index for. edge: The edge dictionary containing source and target information. + block_to_input_index: Dictionary mapping blocks to their current input index count. Returns: - The input index for the block. + int: The input index for the block. + + Raises: + AssertionError: If the target block has multiple input ports but the connection + method hasn't been implemented for that block type. """ if edge["targetHandle"] is not None: @@ -422,11 +538,16 @@ def get_output_index(block: Block, edge: dict) -> int: Get the output index for a block based on the edge data. Args: - block: The block object. + block: The block object to get the output index for. edge: The edge dictionary containing source and target information. Returns: - The output index for the block. + int: The output index for the block. + + Raises: + ValueError: If an invalid source handle is provided for a Splitter block. + AssertionError: If the source block has multiple output ports but the connection + method hasn't been implemented for that block type. """ if edge["sourceHandle"] is not None: if block._port_map_out: @@ -456,6 +577,23 @@ def get_output_index(block: Block, edge: dict) -> int: def make_connections(nodes, edges, blocks) -> list[Connection]: + """ + Create PathSim Connection objects from nodes, edges, and blocks data. + + This function processes the graph structure to create proper connections between blocks, + handling special cases for scopes and different block types with multiple inputs/outputs. + + Args: + nodes: List of node dictionaries containing block information. + edges: List of edge dictionaries defining connections between nodes. + blocks: List of Block objects that have been created from the nodes. + + Returns: + list[Connection]: List of PathSim Connection objects linking block inputs and outputs. + + Note: + This function also handles labeling for Scope and Spectrum blocks automatically. + """ # Create connections based on the sorted edges to match beta order connections_pathsim = [] @@ -526,6 +664,21 @@ def make_events(events_data: list[dict], eval_namespace: dict = None) -> list[Ev def make_default_scope(nodes, blocks) -> tuple[Scope, list[Connection]]: + """ + Create a default Scope block that connects to all other blocks in the simulation. + + This function creates a default scope when no explicit scope exists in the graph, + ensuring that all block outputs are captured for visualization. + + Args: + nodes: List of node dictionaries containing block information (used for labels). + blocks: List of Block objects to connect to the default scope. + + Returns: + tuple: A tuple containing: + - scope_default (Scope): The created default Scope block + - connections_pathsim (list[Connection]): List of connections from blocks to the scope + """ scope_default = Scope( labels=[node["data"]["label"] for node in nodes], ) @@ -577,6 +730,31 @@ def make_var_name(node: dict) -> str: def make_pathsim_model(graph_data: dict) -> tuple[Simulation, float]: + """ + Create a complete PathSim simulation model from graph data. + + This is the main function that orchestrates the creation of a PathSim simulation + from a graph representation. It processes nodes, edges, solver parameters, global + variables, events, and custom Python code to build a complete simulation model. + + Args: + graph_data: Dictionary containing the complete graph representation with keys: + - nodes: List of node dictionaries representing blocks + - edges: List of edge dictionaries representing connections + - solverParams: Dictionary of solver configuration parameters + - globalVariables: Dictionary of global variable definitions + - events: List of event dictionaries (optional) + - pythonCode: Custom Python code to execute (optional) + + Returns: + tuple: A tuple containing: + - simulation (Simulation): The configured PathSim Simulation object + - duration (float): The simulation duration + + Raises: + ValueError: If there are errors in processing any component of the graph data. + Exception: If custom Python code execution fails. + """ nodes = graph_data.get("nodes", []) edges = graph_data.get("edges", []) solver_prms = graph_data.get("solverParams", {}) From 46889a95a1e058b660667a23289177ea8bc554b8 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 16:56:33 -0400 Subject: [PATCH 10/12] formatting --- src/python/pathsim_utils.py | 71 +++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/src/python/pathsim_utils.py b/src/python/pathsim_utils.py index d4300c71..57f4b053 100644 --- a/src/python/pathsim_utils.py +++ b/src/python/pathsim_utils.py @@ -14,9 +14,10 @@ Key mappings are provided for: - Block types (map_str_to_object): Maps string identifiers to PathSim block classes -- Event types (map_str_to_event): Maps string identifiers to PathSim event classes +- Event types (map_str_to_event): Maps string identifiers to PathSim event classes - Solver types (NAME_TO_SOLVER): Maps string identifiers to PathSim solver classes """ + import math import numpy as np from pathsim import Simulation, Connection @@ -167,11 +168,11 @@ def find_node_by_id(node_id: str, nodes: list[dict]) -> dict: """ Find a node by its ID in a list of nodes. - + Args: node_id: The ID of the node to find. nodes: A list of node dictionaries to search through. - + Returns: The node dictionary with the matching ID, or None if not found. """ @@ -181,11 +182,11 @@ def find_node_by_id(node_id: str, nodes: list[dict]) -> dict: def find_block_by_id(block_id: str, blocks: list[Block]) -> Block: """ Find a block by its ID in a list of blocks. - + Args: block_id: The ID of the block to find. blocks: A list of Block objects to search through. - + Returns: The Block object with the matching ID, or None if not found. """ @@ -195,16 +196,16 @@ def find_block_by_id(block_id: str, blocks: list[Block]) -> Block: def make_global_variables(global_vars): """ Validate and execute global variable definitions to make them usable in the simulation. - + Args: - global_vars: A list of dictionaries containing variable definitions, where each + global_vars: A list of dictionaries containing variable definitions, where each dictionary has 'name' and 'value' keys. - + Returns: dict: A namespace dictionary containing the global variables. - + Raises: - ValueError: If a variable name is invalid, is a Python keyword, or if there's + ValueError: If a variable name is invalid, is a Python keyword, or if there's an error evaluating the variable value. """ # Validate and exec global variables so that they are usable later in this script. @@ -248,18 +249,18 @@ def make_global_variables(global_vars): def make_solver_params(solver_prms, eval_namespace=None): """ Process and validate solver parameters from the graph data. - + Args: - solver_prms: Dictionary containing solver parameters including Solver type, + solver_prms: Dictionary containing solver parameters including Solver type, simulation_duration, and other solver-specific parameters. eval_namespace: Optional namespace for evaluating parameter expressions. - + Returns: tuple: A tuple containing: - solver_prms (dict): Processed solver parameters - extra_params (dict): Additional parameters for the solver - duration (float): Simulation duration - + Raises: ValueError: If invalid parameter values are provided or if solver type is unknown. """ @@ -367,15 +368,15 @@ def get_parameters_for_event_class( ): """ Extract and process parameters for an event class from event data. - + Args: event_class: The event class type to create parameters for. event_data: Dictionary containing the event configuration data. eval_namespace: Optional namespace for evaluating expressions and executing functions. - + Returns: dict: A dictionary of parameters ready to be passed to the event class constructor. - + Raises: ValueError: If required parameters are missing, if function code execution fails, or if parameter evaluation fails. @@ -432,15 +433,15 @@ def get_parameters_for_event_class( def get_parameters_for_block_class(block_class, node, eval_namespace): """ Extract and process parameters for a block class from node data. - + Args: block_class: The block class type to create parameters for. node: Dictionary containing the node configuration data. eval_namespace: Namespace for evaluating parameter expressions. - + Returns: dict: A dictionary of parameters ready to be passed to the block class constructor. - + Raises: ValueError: If required parameters are missing or if parameter evaluation fails. """ @@ -475,11 +476,11 @@ def make_blocks( ) -> tuple[list[Block], list[Event]]: """ Create Block objects from node data and collect any associated events. - + Args: nodes: List of node dictionaries containing block configuration data. eval_namespace: Optional namespace for evaluating expressions. - + Returns: tuple: A tuple containing: - blocks (list[Block]): List of created Block objects @@ -510,7 +511,7 @@ def get_input_index(block: Block, edge: dict, block_to_input_index: dict) -> int Returns: int: The input index for the block. - + Raises: AssertionError: If the target block has multiple input ports but the connection method hasn't been implemented for that block type. @@ -543,7 +544,7 @@ def get_output_index(block: Block, edge: dict) -> int: Returns: int: The output index for the block. - + Raises: ValueError: If an invalid source handle is provided for a Splitter block. AssertionError: If the source block has multiple output ports but the connection @@ -579,18 +580,18 @@ def get_output_index(block: Block, edge: dict) -> int: def make_connections(nodes, edges, blocks) -> list[Connection]: """ Create PathSim Connection objects from nodes, edges, and blocks data. - + This function processes the graph structure to create proper connections between blocks, handling special cases for scopes and different block types with multiple inputs/outputs. - + Args: nodes: List of node dictionaries containing block information. edges: List of edge dictionaries defining connections between nodes. blocks: List of Block objects that have been created from the nodes. - + Returns: list[Connection]: List of PathSim Connection objects linking block inputs and outputs. - + Note: This function also handles labeling for Scope and Spectrum blocks automatically. """ @@ -666,14 +667,14 @@ def make_events(events_data: list[dict], eval_namespace: dict = None) -> list[Ev def make_default_scope(nodes, blocks) -> tuple[Scope, list[Connection]]: """ Create a default Scope block that connects to all other blocks in the simulation. - + This function creates a default scope when no explicit scope exists in the graph, ensuring that all block outputs are captured for visualization. - + Args: nodes: List of node dictionaries containing block information (used for labels). blocks: List of Block objects to connect to the default scope. - + Returns: tuple: A tuple containing: - scope_default (Scope): The created default Scope block @@ -732,11 +733,11 @@ def make_var_name(node: dict) -> str: def make_pathsim_model(graph_data: dict) -> tuple[Simulation, float]: """ Create a complete PathSim simulation model from graph data. - + This is the main function that orchestrates the creation of a PathSim simulation from a graph representation. It processes nodes, edges, solver parameters, global variables, events, and custom Python code to build a complete simulation model. - + Args: graph_data: Dictionary containing the complete graph representation with keys: - nodes: List of node dictionaries representing blocks @@ -745,12 +746,12 @@ def make_pathsim_model(graph_data: dict) -> tuple[Simulation, float]: - globalVariables: Dictionary of global variable definitions - events: List of event dictionaries (optional) - pythonCode: Custom Python code to execute (optional) - + Returns: tuple: A tuple containing: - simulation (Simulation): The configured PathSim Simulation object - duration (float): The simulation duration - + Raises: ValueError: If there are errors in processing any component of the graph data. Exception: If custom Python code execution fails. From fd1949cb817b9782d85437114c60b33f6e069218 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 12 Aug 2025 16:59:27 -0400 Subject: [PATCH 11/12] removed fuel-cycle --- src/App.jsx | 2 +- src/components/Sidebar.jsx | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 867656b6..7eddce76 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -324,7 +324,7 @@ const DnDFlow = () => { try { // Modern approach: Use File System Access API for proper "Save As" dialog const fileHandle = await window.showSaveFilePicker({ - suggestedName: 'fuel-cycle-graph.json', + suggestedName: 'pathview_graph.json', types: [{ description: 'JSON files', accept: { diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx index b651e148..4490d4fe 100644 --- a/src/components/Sidebar.jsx +++ b/src/components/Sidebar.jsx @@ -1,18 +1,18 @@ import React, { useState } from 'react'; import { useDnD } from './DnDContext'; import { nodeCategories, getNodeDisplayName } from '../nodeConfig.js'; - + export default () => { const [_, setType] = useDnD(); const [expandedCategories, setExpandedCategories] = useState({ - 'Sources': true, + 'Sources': false, 'Processing': true, 'Math': true, 'Control': false, 'Fuel Cycle': false, 'Output': true }); - + const onDragStart = (event, nodeType) => { setType(nodeType); event.dataTransfer.effectAllowed = 'move'; @@ -39,9 +39,9 @@ export default () => { }; return categoryClasses[categoryName] || 'dndnode'; }; - + return ( -