flowgraph 0.1.2__tar.gz → 0.1.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. {flowgraph-0.1.2/src/flowgraph.egg-info → flowgraph-0.1.7}/PKG-INFO +98 -6
  2. flowgraph-0.1.7/README.md +190 -0
  3. {flowgraph-0.1.2 → flowgraph-0.1.7}/pyproject.toml +21 -1
  4. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/__init__.py +45 -14
  5. flowgraph-0.1.7/src/flowgraph/adapters/calculator.py +120 -0
  6. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/controls.py +19 -10
  7. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/cosapp.py +13 -4
  8. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/data_types.py +22 -4
  9. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/documentation.py +4 -2
  10. flowgraph-0.1.7/src/flowgraph/adapters/field_gradient.py +136 -0
  11. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/field_ops.py +79 -8
  12. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/file_conversion.py +6 -2
  13. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/files.py +74 -60
  14. flowgraph-0.1.7/src/flowgraph/adapters/filters.py +349 -0
  15. flowgraph-0.1.7/src/flowgraph/adapters/image_tools.py +741 -0
  16. flowgraph-0.1.7/src/flowgraph/adapters/imagej.py +232 -0
  17. flowgraph-0.1.7/src/flowgraph/adapters/mesh_analysis.py +282 -0
  18. flowgraph-0.1.7/src/flowgraph/adapters/mesh_composition.py +481 -0
  19. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/mesh_creation_tools.py +67 -13
  20. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/mesh_generations.py +5 -1
  21. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/mesh_ops.py +150 -6
  22. flowgraph-0.1.7/src/flowgraph/adapters/paraview.py +107 -0
  23. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/plaid_bridge.py +39 -15
  24. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/readers.py +94 -11
  25. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/remote_files.py +7 -1
  26. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/simple_sources.py +154 -17
  27. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/sinks.py +35 -4
  28. flowgraph-0.1.7/src/flowgraph/adapters/table_tools.py +128 -0
  29. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/user_code.py +24 -3
  30. flowgraph-0.1.7/src/flowgraph/adapters/vector_tools.py +168 -0
  31. flowgraph-0.1.7/src/flowgraph/adapters/workflow.py +306 -0
  32. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/workflow_interfaces.py +11 -2
  33. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/adapters/writers.py +93 -4
  34. flowgraph-0.1.7/src/flowgraph/adapters/zones.py +311 -0
  35. flowgraph-0.1.7/src/flowgraph/application/file_dependencies.py +136 -0
  36. flowgraph-0.1.7/src/flowgraph/application/port_conversions.py +235 -0
  37. flowgraph-0.1.7/src/flowgraph/application/workflow_cli.py +572 -0
  38. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/application/workflow_core.py +269 -13
  39. flowgraph-0.1.7/src/flowgraph/application/workflow_defaults.py +90 -0
  40. flowgraph-0.1.7/src/flowgraph/application/workflow_execution.py +358 -0
  41. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/application/workflow_io.py +79 -11
  42. flowgraph-0.1.7/src/flowgraph/application/workflow_session.py +436 -0
  43. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/application/workflow_web_catalog.py +26 -5
  44. flowgraph-0.1.7/src/flowgraph/core_cli.py +141 -0
  45. flowgraph-0.1.7/src/flowgraph/domain/filepath.py +77 -0
  46. flowgraph-0.1.7/src/flowgraph/paraview_gateway.py +872 -0
  47. flowgraph-0.1.7/src/flowgraph/server/__init__.py +1 -0
  48. flowgraph-0.1.7/src/flowgraph/server/http.py +315 -0
  49. flowgraph-0.1.7/src/flowgraph/server/jobs.py +223 -0
  50. flowgraph-0.1.7/src/flowgraph/server/worker.py +36 -0
  51. flowgraph-0.1.7/src/flowgraph/server/workspace.py +136 -0
  52. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/testdata/AllFilters.json +2 -2
  53. flowgraph-0.1.7/src/flowgraph/testdata/ColorCardboard.jpg +0 -0
  54. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/version.py +1 -1
  55. {flowgraph-0.1.2 → flowgraph-0.1.7/src/flowgraph.egg-info}/PKG-INFO +98 -6
  56. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph.egg-info/SOURCES.txt +53 -3
  57. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph.egg-info/requires.txt +7 -0
  58. flowgraph-0.1.7/tests/test_array_nodes.py +226 -0
  59. flowgraph-0.1.7/tests/test_array_types.py +177 -0
  60. flowgraph-0.1.7/tests/test_cache_policy.py +191 -0
  61. flowgraph-0.1.7/tests/test_calculator.py +242 -0
  62. flowgraph-0.1.7/tests/test_conditional_workflow.py +243 -0
  63. flowgraph-0.1.7/tests/test_controls.py +123 -0
  64. flowgraph-0.1.7/tests/test_directory_dependencies.py +200 -0
  65. flowgraph-0.1.7/tests/test_extract_field.py +104 -0
  66. flowgraph-0.1.7/tests/test_extract_vector_value.py +109 -0
  67. flowgraph-0.1.7/tests/test_field_gradient.py +231 -0
  68. flowgraph-0.1.7/tests/test_filepath.py +47 -0
  69. flowgraph-0.1.7/tests/test_fluency_optimization.py +119 -0
  70. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_image_tools.py +217 -5
  71. flowgraph-0.1.7/tests/test_imagej.py +267 -0
  72. flowgraph-0.1.7/tests/test_local_server.py +536 -0
  73. flowgraph-0.1.7/tests/test_mesh_analysis.py +340 -0
  74. flowgraph-0.1.7/tests/test_mesh_composition.py +492 -0
  75. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_mesh_creation_tools.py +10 -0
  76. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_mesh_ops.py +56 -0
  77. flowgraph-0.1.7/tests/test_node_selector.py +216 -0
  78. flowgraph-0.1.7/tests/test_packaging.py +180 -0
  79. flowgraph-0.1.7/tests/test_paraview.py +1252 -0
  80. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_plaid_bridge.py +108 -6
  81. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_readers.py +71 -11
  82. flowgraph-0.1.7/tests/test_release.py +235 -0
  83. flowgraph-0.1.7/tests/test_remove_lonely_nodes.py +112 -0
  84. flowgraph-0.1.7/tests/test_scalars_to_array_1d.py +104 -0
  85. flowgraph-0.1.7/tests/test_simple_sources.py +107 -0
  86. flowgraph-0.1.7/tests/test_sinks.py +12 -0
  87. flowgraph-0.1.7/tests/test_table_tools.py +176 -0
  88. flowgraph-0.1.7/tests/test_transfer_fields.py +122 -0
  89. flowgraph-0.1.7/tests/test_user_code_mesh.py +38 -0
  90. flowgraph-0.1.7/tests/test_vector_field_gradient.py +184 -0
  91. flowgraph-0.1.7/tests/test_vector_tools.py +184 -0
  92. flowgraph-0.1.7/tests/test_workflow_cli.py +976 -0
  93. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_workflow_core.py +340 -1
  94. flowgraph-0.1.7/tests/test_workflow_execution.py +538 -0
  95. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_workflow_io.py +85 -1
  96. flowgraph-0.1.7/tests/test_workflow_session.py +634 -0
  97. flowgraph-0.1.7/tests/test_workflow_web_catalog.py +307 -0
  98. flowgraph-0.1.7/tests/test_workspace_directories.py +54 -0
  99. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_writers.py +56 -0
  100. flowgraph-0.1.7/tests/test_zones.py +214 -0
  101. flowgraph-0.1.2/README.md +0 -104
  102. flowgraph-0.1.2/src/flowgraph/adapters/filters.py +0 -173
  103. flowgraph-0.1.2/src/flowgraph/adapters/image_tools.py +0 -394
  104. flowgraph-0.1.2/src/flowgraph/adapters/paraview.py +0 -39
  105. flowgraph-0.1.2/src/flowgraph/adapters/workflow.py +0 -176
  106. flowgraph-0.1.2/src/flowgraph/application/port_conversions.py +0 -63
  107. flowgraph-0.1.2/src/flowgraph/application/wasm_execution.py +0 -132
  108. flowgraph-0.1.2/src/flowgraph/application/workflow_cli.py +0 -417
  109. flowgraph-0.1.2/src/flowgraph/core_cli.py +0 -81
  110. flowgraph-0.1.2/tests/test_packaging.py +0 -53
  111. flowgraph-0.1.2/tests/test_wasm_execution.py +0 -119
  112. flowgraph-0.1.2/tests/test_workflow_cli.py +0 -308
  113. flowgraph-0.1.2/tests/test_workflow_web_catalog.py +0 -50
  114. {flowgraph-0.1.2 → flowgraph-0.1.7}/LICENSE +0 -0
  115. {flowgraph-0.1.2 → flowgraph-0.1.7}/setup.cfg +0 -0
  116. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/__init__.py +0 -0
  117. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/__main__.py +0 -0
  118. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/application/__init__.py +0 -0
  119. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/application/node_registry.py +0 -0
  120. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/application/workflow_history.py +0 -0
  121. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/application/workflow_layout.py +0 -0
  122. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/application/workflows.py +0 -0
  123. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/domain/__init__.py +0 -0
  124. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/domain/mesh_document.py +0 -0
  125. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/examples/AllFilters.py +0 -0
  126. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/examples/convert_format.py +0 -0
  127. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/resources.py +0 -0
  128. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/testdata/FlowGraph.h5 +0 -0
  129. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/testdata/FlowGraph.stl +0 -0
  130. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/testdata/FlowGraph.xdmf +0 -0
  131. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/testdata/SimpleReadMesh.json +0 -0
  132. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/testdata/SpherePoints.csv +0 -0
  133. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph/testdata/muscat-muscat-mesh-conversion.json +0 -0
  134. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph.egg-info/dependency_links.txt +0 -0
  135. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph.egg-info/entry_points.txt +0 -0
  136. {flowgraph-0.1.2 → flowgraph-0.1.7}/src/flowgraph.egg-info/top_level.txt +0 -0
  137. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_core_gui_boundary.py +0 -0
  138. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_cosapp.py +0 -0
  139. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_file_conversion.py +0 -0
  140. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_headless_boundary.py +0 -0
  141. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_muscat_vtk.py +0 -0
  142. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_remote_files.py +0 -0
  143. {flowgraph-0.1.2 → flowgraph-0.1.7}/tests/test_workflow_history.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowgraph
3
- Version: 0.1.2
3
+ Version: 0.1.7
4
4
  Summary: Headless typed workflow engine and execution runtime
5
5
  Author: Felipe Bordeu
6
6
  Maintainer: Felipe Bordeu
@@ -31,10 +31,16 @@ Requires-Dist: scipy>=1.10
31
31
  Requires-Dist: pandas
32
32
  Requires-Dist: h5py
33
33
  Requires-Dist: pillow>=10.0
34
+ Requires-Dist: numpy>=1.24
35
+ Requires-Dist: openpyxl>=3.1.5
36
+ Provides-Extra: imagej
37
+ Requires-Dist: pyimagej; extra == "imagej"
38
+ Requires-Dist: scyjava; extra == "imagej"
34
39
  Provides-Extra: dev
35
40
  Requires-Dist: pytest>=8.0; extra == "dev"
36
41
  Requires-Dist: pytest-cov>=5.0; extra == "dev"
37
42
  Requires-Dist: ruff>=0.6; extra == "dev"
43
+ Requires-Dist: build; extra == "dev"
38
44
  Provides-Extra: ml
39
45
  Requires-Dist: pyplaid; extra == "ml"
40
46
  Provides-Extra: cosapp
@@ -55,7 +61,14 @@ for compatible external clients.
55
61
  > development, experimentation, and early adopter feedback. APIs and workflow
56
62
  > behavior may change before `1.0.0`. See [`Release Policy`](docs/policies/release-policy.md).
57
63
 
58
- ## Development
64
+ ## Incremental workflow execution
65
+
66
+ `WorkflowExecutor` remains stateless. Use `WorkflowSession` for selected targets,
67
+ dependency-aware cache reuse, forced runs and session lifecycle. See
68
+ [`Incremental execution`](doc/reference/incremental-execution.md) for the Python
69
+ API, node safety contracts, transport options and resource limits.
70
+
71
+ ## Development setup
59
72
 
60
73
  ```bash
61
74
  uv sync --extra dev
@@ -72,14 +85,81 @@ The `flowgraph` command is headless and has no GUI runtime dependency:
72
85
 
73
86
  ```bash
74
87
  uv run flowgraph inspect workflow.json
88
+ uv run flowgraph inspect workflow.json --full
89
+ uv run flowgraph inspect workflow.json -i name=value --override node-id.parameter=value
75
90
  uv run flowgraph run workflow.json --input name=value
91
+ uv run flowgraph run workflow.json -i name=value
76
92
  uv run flowgraph run workflow.json --override node-id.parameter=value
77
93
  uv run flowgraph run workflow.json --json-output results.json
78
94
  ```
79
95
 
96
+ Use `--input` or its short form `-i` for each published workflow input; repeat
97
+ the option to provide multiple inputs.
98
+ `flowgraph inspect` displays the resolved default to the right of each published
99
+ input, or marks it as required or having conflicting saved values.
100
+ Inspection is compact by default; add `--full` (or `-f`) to include the workflow
101
+ graph. Arbitrary-code warnings remain visible in both modes.
102
+ Inspection accepts the same `--input` / `-i` and `--override` assignments as
103
+ execution: overrides update the displayed defaults, and explicit inputs take
104
+ precedence and are marked `(--input)`. It never executes nodes or saves changes.
105
+ When an input is omitted, `flowgraph run` uses its downstream node's saved
106
+ parameter value and prints a warning to stderr identifying the input, value,
107
+ and parameter. This also works for directly exported parameters and nested
108
+ workflow inputs. Explicit inputs take precedence; parameter overrides are applied
109
+ before resolving defaults. Inputs without usable saved values remain required,
110
+ and conflicting saved values require an explicit `--input`.
111
+ For examples and warning output, see
112
+ [Omitted inputs and saved parameter values](doc/user-guide/workflows.md#omitted-inputs-and-saved-parameter-values).
113
+
80
114
  Workflows use the versioned `flowgraph-workflow` JSON format. Core validation and
81
115
  execution are UI-independent.
82
116
 
117
+ ### JSON execution boundary
118
+
119
+ Python clients and browser-hosted Python workers use the same entry point:
120
+
121
+ ```python
122
+ from flowgraph.application.workflow_execution import execute_workflow_json
123
+
124
+ result_json = execute_workflow_json(workflow_json)
125
+ ```
126
+
127
+ The response includes execution order, public outputs, retained node values,
128
+ display previews, warnings, and structured errors. A process-local node registry
129
+ is reused, but each call reconstructs its workflow. This API does not provide a
130
+ server, authentication, cancellation, or filesystem isolation.
131
+
132
+ Mesh display previews retain scalar values or vector magnitudes in `fields` and
133
+ `cell_fields`. Multi-component fields additionally expose their original tuples
134
+ in `field_components` and `cell_field_components`, indexed by vertex or surface
135
+ triangle respectively, so viewers can select an individual component without
136
+ rerunning the workflow. These preview projections do not modify the input mesh.
137
+
138
+ The former WASM-specific execution module has been removed without a compatibility
139
+ alias. Browser clients must update their import and rebuild/stage their core wheel
140
+ together; the workflow file and execution response formats are unchanged.
141
+
142
+ ## Experimental local server
143
+
144
+ The prototype branch includes an authenticated, loopback-only execution API:
145
+
146
+ ```bash
147
+ uv run flowgraph serve --workspace /absolute/path/to/existing/workspace
148
+ ```
149
+
150
+ Port 8765 and the allowed editor origin `https://flowgraph-web.fbw-es.com` are
151
+ defaults; explicit `--allow-origin` values replace that origin. The editor still
152
+ requires bearer authentication and browser local-network permission. Click the
153
+ printed **Open editor** link to pass the token and port automatically; keep the
154
+ link private.
155
+
156
+ It runs one workflow at a time in a cancellable native subprocess and provides
157
+ runtime metadata, catalog, and workspace file endpoints. Core is API-only and never
158
+ serves editor assets. Web and desktop clients own their GUI hosting and explicitly
159
+ allow their origin with `--allow-origin`. Native workflow code is **not sandboxed**.
160
+ See [Local server API and limitations](docs/local-server.md) for authentication,
161
+ request/response formats, examples, limits, and shutdown behavior.
162
+
83
163
  ## Package artifacts
84
164
 
85
165
  Build the portable, pure-Python source distribution and wheel with:
@@ -91,12 +171,18 @@ uv build --out-dir dist/
91
171
  The resulting wheel is compatible with all supported Python platforms. See
92
172
  `packaging/README.md` for release details.
93
173
 
94
- The initial supported publication channels are GitHub source releases and
95
- PyPI. Conda, Docker, operating-system package managers, and third-party mirrors
96
- are not supported release channels at this time. See
174
+ The repository also includes a Conda recipe under `packaging/conda/`. FlowGraph
175
+ is distributed through the [`flowgraph` Anaconda channel](https://anaconda.org/channels/flowgraph):
176
+
177
+ ```bash
178
+ conda install -c flowgraph flowgraph
179
+ ```
180
+
181
+ Docker, operating-system package managers, and third-party mirrors are not
182
+ supported release channels at this time. See
97
183
  [`Release Channels`](docs/policies/release-channels.md) for the release policy.
98
184
 
99
- FlowGraph Core declares Python 3.11 or newer. CI covers Python 3.11 and 3.13 on
185
+ FlowGraph Core declares Python 3.11 or newer. CI covers Python 3.11, 3.12, 3.13, and 3.14 on
100
186
  GitHub-hosted Ubuntu, Windows, and macOS runners; a platform/version combination
101
187
  is supported only after its release-candidate job passes. See
102
188
  [`Support Policy`](docs/policies/support-policy.md) for compatibility, deprecation,
@@ -116,6 +202,12 @@ behavior.
116
202
 
117
203
  ## Documentation and support
118
204
 
205
+ - [FlowGraph documentation](https://flowgraph.readthedocs.io/en/latest/)
206
+ - [Built-in node catalog](doc/reference/adapters/index.md) and
207
+ [Python custom-node guide](doc/user-guide/custom-nodes.md).
208
+ - The website documentation lives in `doc/` (outside the Python package).
209
+ To build the Read the Docs site locally, run
210
+ `uv run --with zensical zensical build -f zensical.toml` from this repository.
119
211
  - [`Architecture`](docs/architecture.md) describes the core boundaries and workflow
120
212
  model.
121
213
  - [`Support Policy`](docs/policies/support-policy.md) describes supported environments and
@@ -0,0 +1,190 @@
1
+ # FlowGraph Core
2
+
3
+ `FlowGraph` is the GUI-free Python workflow engine. It provides typed workflow
4
+ composition, validation, persistence, execution, adapters, mesh and image data
5
+ operations, browser-WASM execution support, and metadata-only catalog export
6
+ for compatible external clients.
7
+
8
+ > **Alpha status:** FlowGraph Core `0.1.x` is an alpha series for evaluation,
9
+ > development, experimentation, and early adopter feedback. APIs and workflow
10
+ > behavior may change before `1.0.0`. See [`Release Policy`](docs/policies/release-policy.md).
11
+
12
+ ## Incremental workflow execution
13
+
14
+ `WorkflowExecutor` remains stateless. Use `WorkflowSession` for selected targets,
15
+ dependency-aware cache reuse, forced runs and session lifecycle. See
16
+ [`Incremental execution`](doc/reference/incremental-execution.md) for the Python
17
+ API, node safety contracts, transport options and resource limits.
18
+
19
+ ## Development setup
20
+
21
+ ```bash
22
+ uv sync --extra dev
23
+ uv run pytest
24
+ uv run ruff check .
25
+ ```
26
+
27
+ See [`Contributing`](.github/CONTRIBUTING.md) for prerequisites, development
28
+ workflow, testing, documentation, and pull-request expectations.
29
+
30
+ ## Headless workflows
31
+
32
+ The `flowgraph` command is headless and has no GUI runtime dependency:
33
+
34
+ ```bash
35
+ uv run flowgraph inspect workflow.json
36
+ uv run flowgraph inspect workflow.json --full
37
+ uv run flowgraph inspect workflow.json -i name=value --override node-id.parameter=value
38
+ uv run flowgraph run workflow.json --input name=value
39
+ uv run flowgraph run workflow.json -i name=value
40
+ uv run flowgraph run workflow.json --override node-id.parameter=value
41
+ uv run flowgraph run workflow.json --json-output results.json
42
+ ```
43
+
44
+ Use `--input` or its short form `-i` for each published workflow input; repeat
45
+ the option to provide multiple inputs.
46
+ `flowgraph inspect` displays the resolved default to the right of each published
47
+ input, or marks it as required or having conflicting saved values.
48
+ Inspection is compact by default; add `--full` (or `-f`) to include the workflow
49
+ graph. Arbitrary-code warnings remain visible in both modes.
50
+ Inspection accepts the same `--input` / `-i` and `--override` assignments as
51
+ execution: overrides update the displayed defaults, and explicit inputs take
52
+ precedence and are marked `(--input)`. It never executes nodes or saves changes.
53
+ When an input is omitted, `flowgraph run` uses its downstream node's saved
54
+ parameter value and prints a warning to stderr identifying the input, value,
55
+ and parameter. This also works for directly exported parameters and nested
56
+ workflow inputs. Explicit inputs take precedence; parameter overrides are applied
57
+ before resolving defaults. Inputs without usable saved values remain required,
58
+ and conflicting saved values require an explicit `--input`.
59
+ For examples and warning output, see
60
+ [Omitted inputs and saved parameter values](doc/user-guide/workflows.md#omitted-inputs-and-saved-parameter-values).
61
+
62
+ Workflows use the versioned `flowgraph-workflow` JSON format. Core validation and
63
+ execution are UI-independent.
64
+
65
+ ### JSON execution boundary
66
+
67
+ Python clients and browser-hosted Python workers use the same entry point:
68
+
69
+ ```python
70
+ from flowgraph.application.workflow_execution import execute_workflow_json
71
+
72
+ result_json = execute_workflow_json(workflow_json)
73
+ ```
74
+
75
+ The response includes execution order, public outputs, retained node values,
76
+ display previews, warnings, and structured errors. A process-local node registry
77
+ is reused, but each call reconstructs its workflow. This API does not provide a
78
+ server, authentication, cancellation, or filesystem isolation.
79
+
80
+ Mesh display previews retain scalar values or vector magnitudes in `fields` and
81
+ `cell_fields`. Multi-component fields additionally expose their original tuples
82
+ in `field_components` and `cell_field_components`, indexed by vertex or surface
83
+ triangle respectively, so viewers can select an individual component without
84
+ rerunning the workflow. These preview projections do not modify the input mesh.
85
+
86
+ The former WASM-specific execution module has been removed without a compatibility
87
+ alias. Browser clients must update their import and rebuild/stage their core wheel
88
+ together; the workflow file and execution response formats are unchanged.
89
+
90
+ ## Experimental local server
91
+
92
+ The prototype branch includes an authenticated, loopback-only execution API:
93
+
94
+ ```bash
95
+ uv run flowgraph serve --workspace /absolute/path/to/existing/workspace
96
+ ```
97
+
98
+ Port 8765 and the allowed editor origin `https://flowgraph-web.fbw-es.com` are
99
+ defaults; explicit `--allow-origin` values replace that origin. The editor still
100
+ requires bearer authentication and browser local-network permission. Click the
101
+ printed **Open editor** link to pass the token and port automatically; keep the
102
+ link private.
103
+
104
+ It runs one workflow at a time in a cancellable native subprocess and provides
105
+ runtime metadata, catalog, and workspace file endpoints. Core is API-only and never
106
+ serves editor assets. Web and desktop clients own their GUI hosting and explicitly
107
+ allow their origin with `--allow-origin`. Native workflow code is **not sandboxed**.
108
+ See [Local server API and limitations](docs/local-server.md) for authentication,
109
+ request/response formats, examples, limits, and shutdown behavior.
110
+
111
+ ## Package artifacts
112
+
113
+ Build the portable, pure-Python source distribution and wheel with:
114
+
115
+ ```bash
116
+ uv build --out-dir dist/
117
+ ```
118
+
119
+ The resulting wheel is compatible with all supported Python platforms. See
120
+ `packaging/README.md` for release details.
121
+
122
+ The repository also includes a Conda recipe under `packaging/conda/`. FlowGraph
123
+ is distributed through the [`flowgraph` Anaconda channel](https://anaconda.org/channels/flowgraph):
124
+
125
+ ```bash
126
+ conda install -c flowgraph flowgraph
127
+ ```
128
+
129
+ Docker, operating-system package managers, and third-party mirrors are not
130
+ supported release channels at this time. See
131
+ [`Release Channels`](docs/policies/release-channels.md) for the release policy.
132
+
133
+ FlowGraph Core declares Python 3.11 or newer. CI covers Python 3.11, 3.12, 3.13, and 3.14 on
134
+ GitHub-hosted Ubuntu, Windows, and macOS runners; a platform/version combination
135
+ is supported only after its release-candidate job passes. See
136
+ [`Support Policy`](docs/policies/support-policy.md) for compatibility, deprecation,
137
+ maintenance, and unsupported-use policies.
138
+
139
+ ## Catalog export
140
+
141
+ FlowGraph can export non-executable node metadata for tools that need to author
142
+ or structurally validate workflow JSON:
143
+
144
+ ```bash
145
+ uv run python -m flowgraph.application.workflow_web_catalog node-catalog.json
146
+ ```
147
+
148
+ The catalog intentionally excludes node executors and other callable runtime
149
+ behavior.
150
+
151
+ ## Documentation and support
152
+
153
+ - [FlowGraph documentation](https://flowgraph.readthedocs.io/en/latest/)
154
+ - [Built-in node catalog](doc/reference/adapters/index.md) and
155
+ [Python custom-node guide](doc/user-guide/custom-nodes.md).
156
+ - The website documentation lives in `doc/` (outside the Python package).
157
+ To build the Read the Docs site locally, run
158
+ `uv run --with zensical zensical build -f zensical.toml` from this repository.
159
+ - [`Architecture`](docs/architecture.md) describes the core boundaries and workflow
160
+ model.
161
+ - [`Support Policy`](docs/policies/support-policy.md) describes supported environments and
162
+ compatibility expectations.
163
+ - [`SECURITY.md`](SECURITY.md) explains private vulnerability reporting and the
164
+ security boundaries of workflows and adapters.
165
+ - [`Changelog`](docs/changelog.md) records release changes and known limitations.
166
+ - [`docs/workflow-format.md`](docs/workflow-format.md) documents persistence,
167
+ compatibility, and capability boundaries.
168
+
169
+ ## Optional integrations
170
+
171
+ The `ml` extra enables the PyPlaid adapter and the `cosapp` extra enables the
172
+ CoSApp adapter. Neither extra is part of the minimum core support guarantee.
173
+ Install an extra only when its upstream dependency, license terms, platform
174
+ requirements, and integration behavior have been reviewed for the target
175
+ release:
176
+
177
+ ```bash
178
+ uv sync --extra ml
179
+ uv sync --extra cosapp
180
+ ```
181
+
182
+ Optional adapters may execute external tools or user-provided models. Treat
183
+ their workflows as trusted input and test the exact dependency versions before
184
+ production use.
185
+
186
+ ## License
187
+
188
+ FlowGraph Core is licensed under the [BSD 3-Clause License](LICENSE). Release
189
+ compliance requires review of the exact dependency lockfile, build artifacts,
190
+ third-party notices, native dependencies, and applicable license obligations.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "flowgraph"
7
- version = "0.1.2"
7
+ version = "0.1.7"
8
8
  description = "Headless typed workflow engine and execution runtime"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -35,13 +35,20 @@ dependencies = [
35
35
  "pandas",
36
36
  "h5py",
37
37
  "pillow>=10.0",
38
+ "numpy>=1.24",
39
+ "openpyxl>=3.1.5",
38
40
  ]
39
41
 
40
42
  [project.optional-dependencies]
43
+ imagej = [
44
+ "pyimagej",
45
+ "scyjava",
46
+ ]
41
47
  dev = [
42
48
  "pytest>=8.0",
43
49
  "pytest-cov>=5.0",
44
50
  "ruff>=0.6",
51
+ "build",
45
52
  ]
46
53
  ml = [
47
54
  "pyplaid",
@@ -81,3 +88,16 @@ pythonpath = [".", "src"]
81
88
  target-version = "py311"
82
89
  line-length = 100
83
90
 
91
+ #[tool.uv.sources]
92
+ #muscat = { git = "https://gitlab.com/drti/muscat.git", rev = "ParMmg" }
93
+ ##micromamba install -n uv_muscat_build_packages scotch mmgsuite=*=h* kokkos=*=h*
94
+ ## uv pip install ipywidgets
95
+ ## uv pip install jupyterlab
96
+ ##export OMP_PROC_BIND=spread
97
+ ##export OMP_PLACES=threads
98
+ ##LD_LIBRARY_PATH=/home/fbw/.local/share/mamba/envs/uv_muscat_build_packages/lib/ uv run jupyter lab
99
+
100
+ #[tool.uv]
101
+ #config-settings-package = {muscat = {"cmake.args" = ["-DCMAKE_PREFIX_PATH=/home/fbw/.local/share/mamba/envs/uv_muscat_build_packages/lib/cmake/",
102
+ #"-DSCOTCH_ROOT=/home/fbw/.local/share/mamba/envs/uv_muscat_build_packages/"
103
+ #]}}
@@ -5,6 +5,7 @@ from dataclasses import dataclass
5
5
  from flowgraph.adapters.controls import AVAILABLE_NODES as CONTROL_AVAILABLE_NODES
6
6
  from flowgraph.adapters.cosapp import AVAILABLE_NODES as COSAPP_AVAILABLE_NODES
7
7
  from flowgraph.adapters.documentation import AVAILABLE_NODES as DOCUMENTATION_AVAILABLE_NODES
8
+ from flowgraph.adapters.field_gradient import SCALAR_FIELD_GRADIENT, VECTOR_FIELD_GRADIENT
8
9
  from flowgraph.adapters.field_ops import AVAILABLE_NODES as FIELD_OPS_AVAILABLE_NODES
9
10
  from flowgraph.adapters.file_conversion import MESH_FILE_CONVERSION
10
11
  from flowgraph.adapters.files import (
@@ -14,36 +15,49 @@ from flowgraph.adapters.files import (
14
15
  )
15
16
  from flowgraph.adapters.filters import (
16
17
  CREATE_MUSCAT_ELEMENT_FILTER,
18
+ CREATE_MUSCAT_NODE_FILTER,
17
19
  FILTER_MESH_WITH_MUSCAT,
20
+ SELECTOR_OPERATORS,
18
21
  )
19
22
  from flowgraph.adapters.image_tools import AVAILABLE_NODES as IMAGE_TOOLS_AVAILABLE_NODES
23
+ from flowgraph.adapters.imagej import AVAILABLE_NODES as IMAGEJ_AVAILABLE_NODES
24
+ from flowgraph.adapters.mesh_analysis import MESH_NODES, SET_MESH_FIELD
25
+ from flowgraph.adapters.mesh_composition import FIELD_COMPOSITION_NODES, MESH_COMPOSITION_NODES
20
26
  from flowgraph.adapters.mesh_creation_tools import AVAILABLE_NODES as MESH_CREATION_AVAILABLE_NODES
21
27
  from flowgraph.adapters.mesh_generations import CSV_TO_MESH
22
28
  from flowgraph.adapters.mesh_ops import AVAILABLE_NODES as MESH_OPS_AVAILABLE_NODES
29
+ from flowgraph.adapters.paraview import PARAVIEW_BRIDGE
23
30
  from flowgraph.adapters.plaid_bridge import AVAILABLE_NODES as PLAID_AVAILABLE_NODES
24
31
  from flowgraph.adapters.readers import (
25
32
  LOAD_CSV,
26
33
  LOAD_MESHIO,
27
34
  LOAD_MESHLANE,
28
35
  LOAD_MUSCAT,
36
+ READ_TABLE,
29
37
  )
30
38
  from flowgraph.adapters.remote_files import DOWNLOAD_URL
31
39
  from flowgraph.adapters.simple_sources import (
40
+ SET_ARRAY_1D,
41
+ SET_BOOLEAN,
32
42
  SET_FLOAT,
33
43
  SET_INT,
34
- SET_LIST_FLOAT,
35
44
  SET_LIST_INT,
36
45
  SET_LIST_STR,
37
46
  SET_STRING,
47
+ SET_VEC2D,
48
+ SET_VEC2DI,
38
49
  SET_VEC3D,
39
50
  )
40
51
  from flowgraph.adapters.sinks import AVAILABLE_NODES as SINKS_AVAILABLE_NODES
52
+ from flowgraph.adapters.table_tools import AVAILABLE_NODES as TABLE_TOOLS_AVAILABLE_NODES
41
53
  from flowgraph.adapters.user_code import AVAILABLE_NODES as USER_CODE_AVAILABLE_NODES
54
+ from flowgraph.adapters.vector_tools import AVAILABLE_NODES as VECTOR_TOOLS_AVAILABLE_NODES
42
55
  from flowgraph.adapters.workflow import AVAILABLE_NODES as WORKFLOW_AVAILABLE_NODES
43
56
  from flowgraph.adapters.workflow_interfaces import (
44
57
  AVAILABLE_NODES as WORKFLOW_INTERFACE_AVAILABLE_NODES,
45
58
  )
46
- from flowgraph.adapters.writers import WRITE_MESHIO, WRITE_MESHLANE, WRITE_MUSCAT
59
+ from flowgraph.adapters.writers import WRITE_MESHIO, WRITE_MESHLANE, WRITE_MUSCAT, WRITE_TABLE
60
+ from flowgraph.adapters.zones import AVAILABLE_NODES as ZONE_AVAILABLE_NODES
47
61
  from flowgraph.application.workflow_core import NodeDefinition
48
62
 
49
63
 
@@ -93,9 +107,13 @@ ADAPTERS = AdapterCatalog(
93
107
  AdapterGroup(
94
108
  "Inputs",
95
109
  subgroups=(
96
- AdapterGroup("Scalars", (SET_STRING, SET_INT, SET_FLOAT)),
97
110
  AdapterGroup(
98
- "Lists/Vectors", (SET_LIST_STR, SET_LIST_INT, SET_LIST_FLOAT, SET_VEC3D)
111
+ "Scalars",
112
+ (SET_STRING, SET_BOOLEAN, SET_INT, SET_FLOAT) + CONTROL_AVAILABLE_NODES,
113
+ ),
114
+ AdapterGroup(
115
+ "Lists/Vectors",
116
+ (SET_LIST_STR, SET_LIST_INT, SET_ARRAY_1D, SET_VEC2D, SET_VEC2DI, SET_VEC3D),
99
117
  ),
100
118
  AdapterGroup(
101
119
  "Files",
@@ -108,25 +126,38 @@ ADAPTERS = AdapterCatalog(
108
126
  subgroups=(
109
127
  AdapterGroup(
110
128
  "Readers",
111
- (LOAD_MUSCAT, LOAD_MESHIO, LOAD_MESHLANE, LOAD_CSV),
129
+ (LOAD_MUSCAT, LOAD_MESHIO, LOAD_MESHLANE, LOAD_CSV, READ_TABLE),
112
130
  ),
113
- AdapterGroup("Mesh Gens", (CSV_TO_MESH,)),
114
- AdapterGroup("Mesh Creation", MESH_CREATION_AVAILABLE_NODES),
131
+ AdapterGroup("Mesh Creation", (CSV_TO_MESH,) + MESH_CREATION_AVAILABLE_NODES),
115
132
  AdapterGroup(
116
133
  "Filters",
117
- (CREATE_MUSCAT_ELEMENT_FILTER, FILTER_MESH_WITH_MUSCAT),
134
+ (
135
+ CREATE_MUSCAT_ELEMENT_FILTER,
136
+ CREATE_MUSCAT_NODE_FILTER,
137
+ FILTER_MESH_WITH_MUSCAT,
138
+ )
139
+ + SELECTOR_OPERATORS,
140
+ subgroups=(AdapterGroup("Zones", ZONE_AVAILABLE_NODES),),
141
+ ),
142
+ AdapterGroup(
143
+ "Mesh Ops", MESH_OPS_AVAILABLE_NODES + MESH_NODES + MESH_COMPOSITION_NODES
144
+ ),
145
+ AdapterGroup(
146
+ "Field Ops",
147
+ FIELD_OPS_AVAILABLE_NODES
148
+ + (SET_MESH_FIELD, SCALAR_FIELD_GRADIENT, VECTOR_FIELD_GRADIENT)
149
+ + FIELD_COMPOSITION_NODES,
118
150
  ),
119
- AdapterGroup("Mesh Ops", MESH_OPS_AVAILABLE_NODES),
120
- AdapterGroup("Field Ops", FIELD_OPS_AVAILABLE_NODES),
121
151
  AdapterGroup("File Conversion", (MESH_FILE_CONVERSION,)),
122
- AdapterGroup("Writers", (WRITE_MUSCAT, WRITE_MESHLANE, WRITE_MESHIO)),
152
+ AdapterGroup("Writers", (WRITE_MUSCAT, WRITE_MESHLANE, WRITE_MESHIO, WRITE_TABLE)),
123
153
  ),
124
154
  ),
125
- AdapterGroup("Controls", CONTROL_AVAILABLE_NODES),
126
155
  AdapterGroup("Image Tools", IMAGE_TOOLS_AVAILABLE_NODES),
127
- AdapterGroup("Code", USER_CODE_AVAILABLE_NODES),
156
+ AdapterGroup("Table Tools", TABLE_TOOLS_AVAILABLE_NODES),
157
+ AdapterGroup("Vector Tools", VECTOR_TOOLS_AVAILABLE_NODES),
158
+ AdapterGroup("Code", USER_CODE_AVAILABLE_NODES + IMAGEJ_AVAILABLE_NODES),
128
159
  AdapterGroup("Workflow", WORKFLOW_INTERFACE_AVAILABLE_NODES + WORKFLOW_AVAILABLE_NODES),
129
- AdapterGroup("Sinks", SINKS_AVAILABLE_NODES),
160
+ AdapterGroup("Sinks", SINKS_AVAILABLE_NODES + (PARAVIEW_BRIDGE,)),
130
161
  AdapterGroup("Doc", DOCUMENTATION_AVAILABLE_NODES),
131
162
  AdapterGroup(
132
163
  "External Tools",
@@ -0,0 +1,120 @@
1
+ """Trusted Python-expression calculator with positional and upstream-name inputs."""
2
+
3
+ import builtins
4
+ import keyword
5
+ import re
6
+ from collections import Counter
7
+ from collections.abc import Mapping
8
+ from typing import Any
9
+
10
+ import numpy as np
11
+
12
+ from flowgraph.application.workflow_core import (
13
+ ExecContext,
14
+ NodeDefinition,
15
+ NodeInstance,
16
+ NodeRegistry,
17
+ ParameterDefinition,
18
+ PortDefinition,
19
+ PortDirection,
20
+ WorkflowEdge,
21
+ )
22
+
23
+ from .data_types import ANY, ParameterKind
24
+
25
+
26
+ def _numeric_value(value: Any, label: str) -> Any:
27
+ """Normalize lists and expose numeric array storage through a read-only view."""
28
+ if isinstance(value, list):
29
+ value = np.asarray(value)
30
+ if isinstance(value, np.ndarray):
31
+ if value.dtype.kind not in "buifc":
32
+ raise TypeError(f"Calculator {label} must contain numeric values")
33
+ view = value.view(np.ndarray)
34
+ view.flags.writeable = False
35
+ return view
36
+ if isinstance(value, (bool, int, float, complex, np.number, np.bool_)):
37
+ if np.asarray(value).dtype.kind not in "buifc":
38
+ raise TypeError(f"Calculator {label} must be numeric")
39
+ return value.item() if isinstance(value, np.generic) else value
40
+ raise TypeError(f"Calculator {label} must be a numeric scalar or NumPy array")
41
+
42
+
43
+ def _calculate(
44
+ inputs: Mapping[str, Any],
45
+ parameters: Mapping[str, Any],
46
+ input_edges: Mapping[str, WorkflowEdge],
47
+ ) -> Mapping[str, Any]:
48
+ """Evaluate one trusted expression; this is intentionally not a sandbox."""
49
+ formula = inputs.get("formula", parameters.get("formula", "0"))
50
+ if not isinstance(formula, str) or not formula.strip():
51
+ raise ValueError("Calculator formula must be a non-empty Python expression")
52
+
53
+ namespace = {
54
+ name: _numeric_value(inputs[name], f"input {name!r}")
55
+ for index in range(1, 126)
56
+ if (name := f"input_{index}") in inputs
57
+ }
58
+ data_names = frozenset(namespace)
59
+ names = Counter(edge.source_port for name, edge in input_edges.items() if name in data_names)
60
+ for name, edge in input_edges.items():
61
+ alias = edge.source_port
62
+ if (
63
+ name in data_names
64
+ and names[alias] == 1
65
+ and alias.isidentifier()
66
+ and not keyword.iskeyword(alias)
67
+ and not re.fullmatch(r"input_[0-9]+", alias)
68
+ and alias not in {"np", "__builtins__"}
69
+ and not hasattr(builtins, alias)
70
+ ):
71
+ namespace[alias] = namespace[name]
72
+ namespace.update(np=np, __builtins__=builtins.__dict__)
73
+ try:
74
+ # One shared namespace also makes aliases available inside comprehensions/lambdas.
75
+ result = eval(compile(formula.strip(), "<calculator formula>", "eval"), namespace)
76
+ except Exception as error:
77
+ raise ValueError(f"Calculator formula failed ({type(error).__name__}): {error}") from error
78
+ if isinstance(result, list):
79
+ raise TypeError("Calculator result must be a numeric scalar or NumPy array; use np.array")
80
+ return {"result": _numeric_value(result, "result")}
81
+
82
+
83
+ def _calculator(
84
+ inputs: Mapping[str, Any],
85
+ parameters: Mapping[str, Any],
86
+ _exec_context: ExecContext | None = None,
87
+ ) -> Mapping[str, Any]:
88
+ """Evaluate using numbered names when called without workflow provenance."""
89
+ return _calculate(inputs, parameters, {})
90
+
91
+
92
+ def _calculator_instance(
93
+ _instance: NodeInstance,
94
+ inputs: Mapping[str, Any],
95
+ parameters: Mapping[str, Any],
96
+ _registry: NodeRegistry,
97
+ input_edges: Mapping[str, WorkflowEdge],
98
+ _exec_context: ExecContext,
99
+ ) -> Mapping[str, Any]:
100
+ """Resolve optional aliases from actual upstream output port names."""
101
+ return _calculate(inputs, parameters, input_edges)
102
+
103
+
104
+ CALCULATOR = NodeDefinition(
105
+ id="calculator",
106
+ label="Calculator",
107
+ icon="mdi-calculator",
108
+ description="Evaluate a trusted Python expression with np, numbered inputs and unique aliases.",
109
+ requirements=("py:numpy",),
110
+ ports=(
111
+ PortDefinition("input", PortDirection.INPUT, ANY, "Input", required=False, expandable=125),
112
+ PortDefinition("result", PortDirection.OUTPUT, ANY, "Result"),
113
+ ),
114
+ parameters=(ParameterDefinition("formula", ParameterKind.TEXT, "Formula", "0", "input_1 * 2"),),
115
+ executor=_calculator,
116
+ edge_aware_instance_executor=_calculator_instance,
117
+ cache_policy="always",
118
+ )
119
+
120
+ __all__ = ["CALCULATOR"]