procfunc 0.30.0__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 (87) hide show
  1. procfunc-0.30.0/LICENSE.md +11 -0
  2. procfunc-0.30.0/PKG-INFO +120 -0
  3. procfunc-0.30.0/README.md +97 -0
  4. procfunc-0.30.0/pyproject.toml +67 -0
  5. procfunc-0.30.0/setup.cfg +4 -0
  6. procfunc-0.30.0/src/procfunc/__init__.py +87 -0
  7. procfunc-0.30.0/src/procfunc/color.py +57 -0
  8. procfunc-0.30.0/src/procfunc/compute_graph/__init__.py +28 -0
  9. procfunc-0.30.0/src/procfunc/compute_graph/compute_graph.py +115 -0
  10. procfunc-0.30.0/src/procfunc/compute_graph/node.py +200 -0
  11. procfunc-0.30.0/src/procfunc/compute_graph/operators_info.py +92 -0
  12. procfunc-0.30.0/src/procfunc/compute_graph/proxy.py +173 -0
  13. procfunc-0.30.0/src/procfunc/compute_graph/util.py +282 -0
  14. procfunc-0.30.0/src/procfunc/context.py +115 -0
  15. procfunc-0.30.0/src/procfunc/control.py +174 -0
  16. procfunc-0.30.0/src/procfunc/nodes/__init__.py +66 -0
  17. procfunc-0.30.0/src/procfunc/nodes/bindings_util.py +196 -0
  18. procfunc-0.30.0/src/procfunc/nodes/bpy_node_info.py +280 -0
  19. procfunc-0.30.0/src/procfunc/nodes/compositor.py +2242 -0
  20. procfunc-0.30.0/src/procfunc/nodes/execute/construct_nodes.py +571 -0
  21. procfunc-0.30.0/src/procfunc/nodes/execute/construct_special_cases.py +246 -0
  22. procfunc-0.30.0/src/procfunc/nodes/execute/execute.py +548 -0
  23. procfunc-0.30.0/src/procfunc/nodes/execute/infer_runtime_data_type.py +195 -0
  24. procfunc-0.30.0/src/procfunc/nodes/execute/util.py +247 -0
  25. procfunc-0.30.0/src/procfunc/nodes/func.py +1417 -0
  26. procfunc-0.30.0/src/procfunc/nodes/geo.py +4240 -0
  27. procfunc-0.30.0/src/procfunc/nodes/manifest.json +8769 -0
  28. procfunc-0.30.0/src/procfunc/nodes/math.py +644 -0
  29. procfunc-0.30.0/src/procfunc/nodes/node_function.py +160 -0
  30. procfunc-0.30.0/src/procfunc/nodes/shader.py +2359 -0
  31. procfunc-0.30.0/src/procfunc/nodes/types.py +347 -0
  32. procfunc-0.30.0/src/procfunc/ops/__init__.py +35 -0
  33. procfunc-0.30.0/src/procfunc/ops/_util.py +275 -0
  34. procfunc-0.30.0/src/procfunc/ops/addons.py +59 -0
  35. procfunc-0.30.0/src/procfunc/ops/attr.py +426 -0
  36. procfunc-0.30.0/src/procfunc/ops/collection.py +90 -0
  37. procfunc-0.30.0/src/procfunc/ops/curve.py +18 -0
  38. procfunc-0.30.0/src/procfunc/ops/file.py +126 -0
  39. procfunc-0.30.0/src/procfunc/ops/manifest.json +39149 -0
  40. procfunc-0.30.0/src/procfunc/ops/mesh.py +1510 -0
  41. procfunc-0.30.0/src/procfunc/ops/modifier.py +603 -0
  42. procfunc-0.30.0/src/procfunc/ops/object.py +258 -0
  43. procfunc-0.30.0/src/procfunc/ops/primitives/__init__.py +31 -0
  44. procfunc-0.30.0/src/procfunc/ops/primitives/camera.py +45 -0
  45. procfunc-0.30.0/src/procfunc/ops/primitives/curve.py +71 -0
  46. procfunc-0.30.0/src/procfunc/ops/primitives/light.py +114 -0
  47. procfunc-0.30.0/src/procfunc/ops/primitives/mesh.py +358 -0
  48. procfunc-0.30.0/src/procfunc/ops/uv.py +271 -0
  49. procfunc-0.30.0/src/procfunc/random.py +247 -0
  50. procfunc-0.30.0/src/procfunc/tracer/__init__.py +43 -0
  51. procfunc-0.30.0/src/procfunc/tracer/decorator.py +121 -0
  52. procfunc-0.30.0/src/procfunc/tracer/patch.py +494 -0
  53. procfunc-0.30.0/src/procfunc/tracer/proxy.py +127 -0
  54. procfunc-0.30.0/src/procfunc/tracer/trace.py +222 -0
  55. procfunc-0.30.0/src/procfunc/transforms/__init__.py +49 -0
  56. procfunc-0.30.0/src/procfunc/transforms/cleanup.py +214 -0
  57. procfunc-0.30.0/src/procfunc/transforms/convert.py +20 -0
  58. procfunc-0.30.0/src/procfunc/transforms/distribution.py +191 -0
  59. procfunc-0.30.0/src/procfunc/transforms/extract_materials.py +116 -0
  60. procfunc-0.30.0/src/procfunc/transforms/infer_distribution.py +326 -0
  61. procfunc-0.30.0/src/procfunc/transforms/parameters.py +15 -0
  62. procfunc-0.30.0/src/procfunc/transforms/util.py +35 -0
  63. procfunc-0.30.0/src/procfunc/transpiler/__init__.py +24 -0
  64. procfunc-0.30.0/src/procfunc/transpiler/bpy_to_computegraph.py +1348 -0
  65. procfunc-0.30.0/src/procfunc/transpiler/codegen.py +919 -0
  66. procfunc-0.30.0/src/procfunc/transpiler/identifiers.py +595 -0
  67. procfunc-0.30.0/src/procfunc/transpiler/main.py +299 -0
  68. procfunc-0.30.0/src/procfunc/types.py +380 -0
  69. procfunc-0.30.0/src/procfunc/util/__init__.py +0 -0
  70. procfunc-0.30.0/src/procfunc/util/bpy_info.py +145 -0
  71. procfunc-0.30.0/src/procfunc/util/camera.py +0 -0
  72. procfunc-0.30.0/src/procfunc/util/keyframe.py +70 -0
  73. procfunc-0.30.0/src/procfunc/util/log.py +96 -0
  74. procfunc-0.30.0/src/procfunc/util/manifest.py +121 -0
  75. procfunc-0.30.0/src/procfunc/util/pytree.py +343 -0
  76. procfunc-0.30.0/src/procfunc/util/teardown.py +37 -0
  77. procfunc-0.30.0/src/procfunc.egg-info/PKG-INFO +120 -0
  78. procfunc-0.30.0/src/procfunc.egg-info/SOURCES.txt +85 -0
  79. procfunc-0.30.0/src/procfunc.egg-info/dependency_links.txt +1 -0
  80. procfunc-0.30.0/src/procfunc.egg-info/requires.txt +13 -0
  81. procfunc-0.30.0/src/procfunc.egg-info/top_level.txt +1 -0
  82. procfunc-0.30.0/tests/test_asset.py +228 -0
  83. procfunc-0.30.0/tests/test_compute_graph.py +63 -0
  84. procfunc-0.30.0/tests/test_dedup_names.py +18 -0
  85. procfunc-0.30.0/tests/test_ops.py +480 -0
  86. procfunc-0.30.0/tests/test_pytree.py +45 -0
  87. procfunc-0.30.0/tests/test_trace.py +142 -0
@@ -0,0 +1,11 @@
1
+ Copyright 2026 Princeton University
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+
9
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: procfunc
3
+ Version: 0.30.0
4
+ Summary: A framework for compositional procedural generation
5
+ License-Expression: BSD-3-Clause
6
+ Project-URL: Homepage, https://github.com/princeton-vl/procfunc
7
+ Project-URL: Repository, https://github.com/princeton-vl/procfunc
8
+ Requires-Python: >=3.11
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE.md
11
+ Requires-Dist: bpy==4.2.0
12
+ Requires-Dist: numpy<2
13
+ Requires-Dist: pandas
14
+ Provides-Extra: dev
15
+ Requires-Dist: pytest; extra == "dev"
16
+ Requires-Dist: pytest-xdist; extra == "dev"
17
+ Requires-Dist: ruff<0.16,>=0.15; extra == "dev"
18
+ Requires-Dist: ty; extra == "dev"
19
+ Provides-Extra: docs
20
+ Requires-Dist: sphinx; extra == "docs"
21
+ Requires-Dist: sphinx-rtd-theme; extra == "docs"
22
+ Dynamic: license-file
23
+
24
+ # ProcFunc: Function-Oriented Abstractions for Procedural 3D Generation in Python
25
+
26
+ [**Documentation**](#documentation)
27
+ | [**Research Paper**](#paper)
28
+ | [**Documentation**](#paper)
29
+ | [**Transpiling**](#transpile-a-blender-file-to-procfunc-code)
30
+ | [**Experiments**](#experiments)
31
+ | [**Contributing**](#contributing)
32
+
33
+ This repository contains only the Primitives API, Transpiler and Tracer from our research paper.
34
+
35
+ The pre-made procedural generators are coming soon as part of [infinigen](https://github.com/princeton-vl/infinigen).
36
+
37
+ ### Installation
38
+
39
+ Use [uv](https://docs.astral.sh/uv/getting-started/installation/) or your favorite package manager to install procfunc via pip:
40
+ ```bash
41
+ uv pip install procfunc
42
+ ```
43
+
44
+ Note: ProcFunc depends on `bpy==4.2.0` which then requires Python==3.11.x. Other version are not yet supported.
45
+
46
+ Since we have not yet reached [semver 1.0.0](https://semver.org/) we have not yet finalized procfunc's interface.
47
+ In the meantime, each 0.X.0 may introduce interface changes. Please pin `uv add procfunc<0.XX` where X is the current version.
48
+
49
+ ### Usage
50
+
51
+ See [procfunc.readthedocs.io](https://procfunc.readthedocs.io) for available functions
52
+
53
+ Please create Github Issues for any bugs or unclear interfaces!
54
+
55
+ ##### Transpile a blender file to ProcFunc code
56
+
57
+ <p float="left">
58
+ <img src="examples/transpile_simple_chair/blender_screenshot.png" height="200" />
59
+ <img src="examples/transpile_simple_chair/code_screenshot.png" height="200" />
60
+ </p>
61
+
62
+ Convert a Blender geometry node tree into procfunc Python code by downloading our example blend and executing the transpiler:
63
+ ```bash
64
+ wget https://raw.githubusercontent.com/princeton-vl/procfunc/main/examples/transpile_simple_chair/simple_chair.blend
65
+ uv run python -m procfunc.transpiler.main simple_chair.blend --node_trees simple_chair --output transpiled_code.py
66
+ ```
67
+
68
+ See the expected output in [`examples/transpile_simple_chair/transpiled_code.py`](examples/transpile_simple_chair/transpiled_code.py).
69
+ To use the code, you can add `pf.ops.file.save_blend("test.blend")` to the end of it, then open the generated blender file.
70
+ You can also open and edit the blender geonodes prior to transpiling in order to generate different procfunc code.
71
+
72
+ ### Paper
73
+
74
+ If you find procfunc useful, please cite our paper:
75
+ ```
76
+ @misc{raistrick2026procfunc,
77
+ title={ProcFunc: Function-Oriented Abstractions for Procedural 3D Generation in Python},
78
+ author={Alexander Raistrick and Karhan Kayan and Jack Nugent and David Yan and Lingjie Mei and Meenal Parakh and Hongyu Wen and Dylan Li and Yiming Zuo and Erich Liang and Jia Deng},
79
+ year={2026},
80
+ eprint={2604.26943},
81
+ archivePrefix={arXiv},
82
+ primaryClass={cs.CV},
83
+ url={https://arxiv.org/abs/2604.26943},
84
+ }
85
+ ```
86
+
87
+ ### Experiments
88
+
89
+ See [experiments/EXPERIMENTS.md](experiments/EXPERIMENTS.md)
90
+
91
+ NOTE: experiments are only intended to be correct when using the `experiments` branch, which will not see major updates.
92
+
93
+ ### Contributing
94
+
95
+ Please create an issue for any proposed features to discuss them before implementing.
96
+
97
+ ##### Developer Installation
98
+ ```bash
99
+ git clone git@github.com:princeton-vl/procfunc.git
100
+ cd procfunc
101
+ uv venv
102
+ uv pip install -e ".[dev]"
103
+ ```
104
+
105
+ ##### Tools
106
+
107
+ ```bash
108
+ uv run ruff format
109
+ uv run ruff check --fix
110
+ uv run pytest
111
+ make docs
112
+ ```
113
+
114
+ ##### Todos / Sharp Edges
115
+
116
+ Add optional support for bpy==4.x and 5.x and maybe 3.6, all under the same procfunc interface.
117
+
118
+ pf.ops is missing some blender functions and arguments, especially returning "selection" masks for some cases.
119
+
120
+ Assets like pf.MeshObject and pf.Material are not currently cleaned up upon going out of scope
@@ -0,0 +1,97 @@
1
+ # ProcFunc: Function-Oriented Abstractions for Procedural 3D Generation in Python
2
+
3
+ [**Documentation**](#documentation)
4
+ | [**Research Paper**](#paper)
5
+ | [**Documentation**](#paper)
6
+ | [**Transpiling**](#transpile-a-blender-file-to-procfunc-code)
7
+ | [**Experiments**](#experiments)
8
+ | [**Contributing**](#contributing)
9
+
10
+ This repository contains only the Primitives API, Transpiler and Tracer from our research paper.
11
+
12
+ The pre-made procedural generators are coming soon as part of [infinigen](https://github.com/princeton-vl/infinigen).
13
+
14
+ ### Installation
15
+
16
+ Use [uv](https://docs.astral.sh/uv/getting-started/installation/) or your favorite package manager to install procfunc via pip:
17
+ ```bash
18
+ uv pip install procfunc
19
+ ```
20
+
21
+ Note: ProcFunc depends on `bpy==4.2.0` which then requires Python==3.11.x. Other version are not yet supported.
22
+
23
+ Since we have not yet reached [semver 1.0.0](https://semver.org/) we have not yet finalized procfunc's interface.
24
+ In the meantime, each 0.X.0 may introduce interface changes. Please pin `uv add procfunc<0.XX` where X is the current version.
25
+
26
+ ### Usage
27
+
28
+ See [procfunc.readthedocs.io](https://procfunc.readthedocs.io) for available functions
29
+
30
+ Please create Github Issues for any bugs or unclear interfaces!
31
+
32
+ ##### Transpile a blender file to ProcFunc code
33
+
34
+ <p float="left">
35
+ <img src="examples/transpile_simple_chair/blender_screenshot.png" height="200" />
36
+ <img src="examples/transpile_simple_chair/code_screenshot.png" height="200" />
37
+ </p>
38
+
39
+ Convert a Blender geometry node tree into procfunc Python code by downloading our example blend and executing the transpiler:
40
+ ```bash
41
+ wget https://raw.githubusercontent.com/princeton-vl/procfunc/main/examples/transpile_simple_chair/simple_chair.blend
42
+ uv run python -m procfunc.transpiler.main simple_chair.blend --node_trees simple_chair --output transpiled_code.py
43
+ ```
44
+
45
+ See the expected output in [`examples/transpile_simple_chair/transpiled_code.py`](examples/transpile_simple_chair/transpiled_code.py).
46
+ To use the code, you can add `pf.ops.file.save_blend("test.blend")` to the end of it, then open the generated blender file.
47
+ You can also open and edit the blender geonodes prior to transpiling in order to generate different procfunc code.
48
+
49
+ ### Paper
50
+
51
+ If you find procfunc useful, please cite our paper:
52
+ ```
53
+ @misc{raistrick2026procfunc,
54
+ title={ProcFunc: Function-Oriented Abstractions for Procedural 3D Generation in Python},
55
+ author={Alexander Raistrick and Karhan Kayan and Jack Nugent and David Yan and Lingjie Mei and Meenal Parakh and Hongyu Wen and Dylan Li and Yiming Zuo and Erich Liang and Jia Deng},
56
+ year={2026},
57
+ eprint={2604.26943},
58
+ archivePrefix={arXiv},
59
+ primaryClass={cs.CV},
60
+ url={https://arxiv.org/abs/2604.26943},
61
+ }
62
+ ```
63
+
64
+ ### Experiments
65
+
66
+ See [experiments/EXPERIMENTS.md](experiments/EXPERIMENTS.md)
67
+
68
+ NOTE: experiments are only intended to be correct when using the `experiments` branch, which will not see major updates.
69
+
70
+ ### Contributing
71
+
72
+ Please create an issue for any proposed features to discuss them before implementing.
73
+
74
+ ##### Developer Installation
75
+ ```bash
76
+ git clone git@github.com:princeton-vl/procfunc.git
77
+ cd procfunc
78
+ uv venv
79
+ uv pip install -e ".[dev]"
80
+ ```
81
+
82
+ ##### Tools
83
+
84
+ ```bash
85
+ uv run ruff format
86
+ uv run ruff check --fix
87
+ uv run pytest
88
+ make docs
89
+ ```
90
+
91
+ ##### Todos / Sharp Edges
92
+
93
+ Add optional support for bpy==4.x and 5.x and maybe 3.6, all under the same procfunc interface.
94
+
95
+ pf.ops is missing some blender functions and arguments, especially returning "selection" masks for some cases.
96
+
97
+ Assets like pf.MeshObject and pf.Material are not currently cleaned up upon going out of scope
@@ -0,0 +1,67 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "procfunc"
7
+ version = "0.30.0"
8
+ description = "A framework for compositional procedural generation"
9
+ readme = "README.md"
10
+ license = "BSD-3-Clause"
11
+ requires-python = ">=3.11"
12
+ dependencies = [
13
+ "bpy==4.2.0",
14
+ "numpy<2",
15
+ "pandas",
16
+ ]
17
+
18
+ [project.urls]
19
+ Homepage = "https://github.com/princeton-vl/procfunc"
20
+ Repository = "https://github.com/princeton-vl/procfunc"
21
+
22
+ [project.optional-dependencies]
23
+ dev = [
24
+ "pytest",
25
+ "pytest-xdist",
26
+ "ruff>=0.15,<0.16",
27
+ "ty"
28
+ ]
29
+ docs = [
30
+ "sphinx",
31
+ "sphinx-rtd-theme",
32
+ ]
33
+
34
+ [tool.setuptools.packages.find]
35
+ where = ["src"]
36
+
37
+ [tool.setuptools.package-data]
38
+ procfunc = ["**/*.json"]
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = "tests"
42
+
43
+ [tool.ruff]
44
+ exclude = ["examples", "experiments"]
45
+
46
+ [tool.ruff.lint]
47
+
48
+ select = [
49
+ "E",
50
+ "I",
51
+ "F",
52
+ "S102", # no exec(),
53
+ "TID251", # custom banned imports
54
+ "TID252", # relative imports only allowed for siblings
55
+
56
+ ]
57
+ ignore = [
58
+ "E501", # over-length lines, formatter should handle it
59
+ "E741", # ambigous variable name
60
+ ]
61
+
62
+ [tool.ruff.lint.per-file-ignores]
63
+ "__init__.py" = ["F401"]
64
+
65
+ [tool.ty.rules]
66
+ unresolved-import = "ignore"
67
+ unresolved-attribute = "ignore"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,87 @@
1
+ # ruff: noqa: I001, F401
2
+ # ensure this gets imported first so that mathutils etc is available even if later modules dont import bpy
3
+ import bpy
4
+
5
+ __version__ = "0.30.0"
6
+
7
+ from numpy.random import Generator as RNG
8
+
9
+ # ensure these are always imported first and in the right order
10
+ import bpy as _bpy
11
+ import mathutils as _mu
12
+
13
+ from . import (
14
+ compute_graph,
15
+ control,
16
+ nodes,
17
+ ops,
18
+ random,
19
+ tracer,
20
+ util,
21
+ context,
22
+ color,
23
+ transforms,
24
+ )
25
+ from .types import (
26
+ Vector,
27
+ Color,
28
+ Euler,
29
+ Quaternion,
30
+ Matrix,
31
+ BVHTree,
32
+ Object,
33
+ CameraObject,
34
+ MeshObject,
35
+ CurveObject,
36
+ VolumeObject,
37
+ EmptyObject,
38
+ ArmatureObject,
39
+ HairObject,
40
+ LatticeObject,
41
+ LightObject,
42
+ LightProbeObject,
43
+ MetaObject,
44
+ Material,
45
+ Texture,
46
+ Collection,
47
+ Image,
48
+ ViewLayer,
49
+ Asset,
50
+ World,
51
+ )
52
+ from .nodes import ProcNode, Shader, NodeDataType
53
+ from .tracer import trace, autowrap_module, add_search_scope
54
+ from .util.manifest import module_path
55
+
56
+ autowrap_module(random)
57
+ autowrap_module(color)
58
+ add_search_scope(nodes)
59
+ add_search_scope(ops)
60
+
61
+ __all__ = [
62
+ # Subpackages
63
+ "compute_graph",
64
+ "control",
65
+ "context",
66
+ "color",
67
+ "nodes",
68
+ "ops",
69
+ "random",
70
+ "tracer",
71
+ "transforms",
72
+ "util",
73
+ # Node graph primitives
74
+ "ProcNode",
75
+ "Shader",
76
+ "NodeDataType",
77
+ # Tracing entrypoints
78
+ "trace",
79
+ # Utilities
80
+ "RNG",
81
+ "module_path",
82
+ # NOTE: Blender wrapper types (Object, MeshObject, Material, Texture, ...)
83
+ # are re-exported above for convenience but live in procfunc.types — see
84
+ # that page for documentation. Blender/mathutils re-exports (Vector, Color,
85
+ # Euler, Quaternion, Matrix, BVHTree, NodeGroup, Scene, ViewLayer) are
86
+ # likewise kept importable but documented upstream by Blender.
87
+ ]
@@ -0,0 +1,57 @@
1
+ import numpy as np
2
+
3
+ from procfunc import types as t
4
+
5
+
6
+ def hsv_color(
7
+ hsv: np.ndarray | tuple | None = None,
8
+ *,
9
+ hue: float | None = None,
10
+ saturation: float | None = None,
11
+ value: float | None = None,
12
+ ) -> t.Color:
13
+ color = t.Color()
14
+ if hsv is not None:
15
+ color.hsv = hsv
16
+ else:
17
+ color.hsv = (hue, saturation, value)
18
+ return color
19
+
20
+
21
+ hsv_to_rgba = hsv_color
22
+
23
+
24
+ def rgb_color(
25
+ r: float | None = None,
26
+ g: float | None = None,
27
+ b: float | None = None,
28
+ rgb: np.ndarray | None = None,
29
+ ) -> t.Color:
30
+ color = t.Color()
31
+ if rgb is not None:
32
+ color.r, color.g, color.b = rgb
33
+ else:
34
+ color.r, color.g, color.b = r, g, b
35
+ return color
36
+
37
+
38
+ def _srgb_to_linearrgb(c):
39
+ if c < 0:
40
+ return 0
41
+ elif c < 0.04045:
42
+ return c / 12.92
43
+ else:
44
+ return ((c + 0.055) / 1.055) ** 2.4
45
+
46
+
47
+ def _hex_to_rgb(h: int, alpha: float = 1):
48
+ r = (h & 0xFF0000) >> 16
49
+ g = (h & 0x00FF00) >> 8
50
+ b = h & 0x0000FF
51
+ return tuple([_srgb_to_linearrgb(c / 0xFF) for c in (r, g, b)])
52
+
53
+
54
+ def hex_color(h: int, alpha: float = 1):
55
+ c = t.Color()
56
+ c.r, c.g, c.b = _hex_to_rgb(h, alpha)
57
+ return c
@@ -0,0 +1,28 @@
1
+ from .compute_graph import (
2
+ ComputeGraph,
3
+ )
4
+ from .node import (
5
+ ConstantNode,
6
+ FunctionCallNode,
7
+ GetAttributeNode,
8
+ InputPlaceholderNode,
9
+ MethodCallNode,
10
+ MutatedArgumentNode,
11
+ Node,
12
+ ProceduralNode,
13
+ SubgraphCallNode,
14
+ normalize_args_to_kwargs,
15
+ )
16
+ from .operators_info import OperatorType
17
+ from .proxy import AttributeProxy, Proxy
18
+ from .util import (
19
+ LiteralConstant,
20
+ graph_nodes_equal,
21
+ transform_compute_graph,
22
+ transform_nodetree,
23
+ traverse_breadth_first,
24
+ traverse_depth_first,
25
+ traverse_depth_first_node,
26
+ traverse_nested_graphs,
27
+ usages_per_node,
28
+ )
@@ -0,0 +1,115 @@
1
+ import itertools
2
+ import logging
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+ from procfunc.util.pytree import PyTree
7
+
8
+ from .node import Node
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ def _evaluate_node(node: Node) -> Any:
14
+ if node.result is not None:
15
+ return node.result
16
+
17
+ for arg in itertools.chain(node.args, node.kwargs.values()):
18
+ if isinstance(arg, Node):
19
+ arg.result = _evaluate_node(arg)
20
+
21
+ arg_eval, kwarg_eval = node.inputs.map(
22
+ lambda x: x.result if isinstance(x, Node) else x
23
+ ).obj()
24
+
25
+ # match node:
26
+ # case cg.FunctionCallNode:
27
+ # return node.func(*arg_vals, **kwarg_vals)
28
+ # case cg.PlaceholderNode:
29
+ # raise NotImplementedError(
30
+ # f"Placeholder {node!r} or '<unnamed>'} should not be evaluated - "
31
+ # "its .result should be populated in advance"
32
+ # )
33
+ # case cg.MutatedArgumentNode:
34
+ # # Evaluate the mutation call first (for side effects), then return the original object
35
+ # mutation_call_node = node.args[1]
36
+ # _evaluate_node(mutation_call_node)
37
+ # return (
38
+ # node.args[0].result if isinstance(node.args[0], Node) else node.args[0]
39
+ # )
40
+ # case _:
41
+ # raise NotImplementedError(f"Unsupported node operation: {node.kind}")
42
+
43
+
44
+ def _clear_node_results(node: Node):
45
+ node.result = None
46
+ for arg in itertools.chain(node.args, node.kwargs.values()):
47
+ if isinstance(arg, Node) and arg.result is not None:
48
+ _clear_node_results(arg)
49
+
50
+
51
+ @dataclass
52
+ class ComputeGraph:
53
+ inputs: PyTree[Any, Node]
54
+ outputs: PyTree[Any, Node]
55
+ name: str
56
+ metadata: dict[str, Any]
57
+
58
+ def __post_init__(self):
59
+ # input_names = set(self.inputs.names())
60
+ # if len(input_names) != len(set(input_names)):
61
+ # raise ValueError(f"Input names had duplicates: {input_names}")
62
+
63
+ # output_names = set(self.outputs.names())
64
+ # if len(output_names) != len(set(output_names)):
65
+ # raise ValueError(f"Output names had duplicates: {output_names}")
66
+ pass
67
+
68
+ def __repr__(self):
69
+ return f"{self.__class__.__name__}({self.name!r})"
70
+
71
+ def clear_values(self):
72
+ for node in self.outputs.values():
73
+ _clear_node_results(node)
74
+
75
+ def __call__(
76
+ self,
77
+ *args,
78
+ allow_clear: bool = True,
79
+ **kwargs,
80
+ ):
81
+ """
82
+ Execute the compute graph. If this graph came from a tracer,
83
+ this should be exactly equivelant to executing the original python function.
84
+ """
85
+
86
+ raise NotImplementedError("Not implemented")
87
+
88
+ if len(args) != len(self.inputs):
89
+ raise ValueError(f"Expected {len(self.inputs)} arguments, got {len(args)}")
90
+
91
+ if allow_clear:
92
+ self.clear_values()
93
+
94
+ extra_kwargs = self.kwarg_nodes.keys() - kwargs.keys()
95
+ if extra_kwargs:
96
+ raise ValueError(
97
+ f"{self.__class__.__name__} {self.name!r} got unexpected keyword arguments: {extra_kwargs}"
98
+ )
99
+
100
+ missing_kwargs = kwargs.keys() - self.kwarg_nodes.keys()
101
+ if missing_kwargs:
102
+ raise ValueError(
103
+ f"{self.__class__.__name__} {self.name!r} had missing keyword arguments: {missing_kwargs}"
104
+ )
105
+
106
+ for arg, arg_node in zip(args, self.arg_nodes):
107
+ arg_node.result = arg
108
+
109
+ for k, v in kwargs.items():
110
+ self.kwarg_nodes[k].result = v
111
+
112
+ for node in self.outputs.values():
113
+ _evaluate_node(node)
114
+
115
+ return {name: node.result for name, node in self.outputs.items()}