procfunc 0.30.0__py3-none-any.whl
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.
- procfunc/__init__.py +87 -0
- procfunc/color.py +57 -0
- procfunc/compute_graph/__init__.py +28 -0
- procfunc/compute_graph/compute_graph.py +115 -0
- procfunc/compute_graph/node.py +200 -0
- procfunc/compute_graph/operators_info.py +92 -0
- procfunc/compute_graph/proxy.py +173 -0
- procfunc/compute_graph/util.py +282 -0
- procfunc/context.py +115 -0
- procfunc/control.py +174 -0
- procfunc/nodes/__init__.py +66 -0
- procfunc/nodes/bindings_util.py +196 -0
- procfunc/nodes/bpy_node_info.py +280 -0
- procfunc/nodes/compositor.py +2242 -0
- procfunc/nodes/execute/construct_nodes.py +571 -0
- procfunc/nodes/execute/construct_special_cases.py +246 -0
- procfunc/nodes/execute/execute.py +548 -0
- procfunc/nodes/execute/infer_runtime_data_type.py +195 -0
- procfunc/nodes/execute/util.py +247 -0
- procfunc/nodes/func.py +1417 -0
- procfunc/nodes/geo.py +4240 -0
- procfunc/nodes/manifest.json +8769 -0
- procfunc/nodes/math.py +644 -0
- procfunc/nodes/node_function.py +160 -0
- procfunc/nodes/shader.py +2359 -0
- procfunc/nodes/types.py +347 -0
- procfunc/ops/__init__.py +35 -0
- procfunc/ops/_util.py +275 -0
- procfunc/ops/addons.py +59 -0
- procfunc/ops/attr.py +426 -0
- procfunc/ops/collection.py +90 -0
- procfunc/ops/curve.py +18 -0
- procfunc/ops/file.py +126 -0
- procfunc/ops/manifest.json +39149 -0
- procfunc/ops/mesh.py +1510 -0
- procfunc/ops/modifier.py +603 -0
- procfunc/ops/object.py +258 -0
- procfunc/ops/primitives/__init__.py +31 -0
- procfunc/ops/primitives/camera.py +45 -0
- procfunc/ops/primitives/curve.py +71 -0
- procfunc/ops/primitives/light.py +114 -0
- procfunc/ops/primitives/mesh.py +358 -0
- procfunc/ops/uv.py +271 -0
- procfunc/random.py +247 -0
- procfunc/tracer/__init__.py +43 -0
- procfunc/tracer/decorator.py +121 -0
- procfunc/tracer/patch.py +494 -0
- procfunc/tracer/proxy.py +127 -0
- procfunc/tracer/trace.py +222 -0
- procfunc/transforms/__init__.py +49 -0
- procfunc/transforms/cleanup.py +214 -0
- procfunc/transforms/convert.py +20 -0
- procfunc/transforms/distribution.py +191 -0
- procfunc/transforms/extract_materials.py +116 -0
- procfunc/transforms/infer_distribution.py +326 -0
- procfunc/transforms/parameters.py +15 -0
- procfunc/transforms/util.py +35 -0
- procfunc/transpiler/__init__.py +24 -0
- procfunc/transpiler/bpy_to_computegraph.py +1348 -0
- procfunc/transpiler/codegen.py +919 -0
- procfunc/transpiler/identifiers.py +595 -0
- procfunc/transpiler/main.py +299 -0
- procfunc/types.py +380 -0
- procfunc/util/__init__.py +0 -0
- procfunc/util/bpy_info.py +145 -0
- procfunc/util/camera.py +0 -0
- procfunc/util/keyframe.py +70 -0
- procfunc/util/log.py +96 -0
- procfunc/util/manifest.py +121 -0
- procfunc/util/pytree.py +343 -0
- procfunc/util/teardown.py +37 -0
- procfunc-0.30.0.dist-info/METADATA +120 -0
- procfunc-0.30.0.dist-info/RECORD +76 -0
- procfunc-0.30.0.dist-info/WHEEL +5 -0
- procfunc-0.30.0.dist-info/licenses/LICENSE.md +11 -0
- procfunc-0.30.0.dist-info/top_level.txt +1 -0
procfunc/random.py
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TypeVar
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
import procfunc as pf
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pf.tracer.primitive(allow_exec=True)
|
|
14
|
+
def uniform(
|
|
15
|
+
rng: np.random.Generator,
|
|
16
|
+
low: float,
|
|
17
|
+
high: float,
|
|
18
|
+
) -> float:
|
|
19
|
+
return rng.uniform(low, high)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pf.tracer.primitive(allow_exec=True)
|
|
23
|
+
def normal(
|
|
24
|
+
rng: np.random.Generator,
|
|
25
|
+
mean: float,
|
|
26
|
+
std: float,
|
|
27
|
+
) -> float:
|
|
28
|
+
return rng.normal(mean, std)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pf.tracer.primitive(allow_exec=True)
|
|
32
|
+
def randint(
|
|
33
|
+
rng: np.random.Generator,
|
|
34
|
+
low: int,
|
|
35
|
+
high: int,
|
|
36
|
+
) -> int:
|
|
37
|
+
return rng.integers(low, high)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pf.tracer.primitive(allow_exec=True)
|
|
41
|
+
def uniform_tails(
|
|
42
|
+
rng: np.random.Generator,
|
|
43
|
+
low: float,
|
|
44
|
+
high: float,
|
|
45
|
+
tail_pct: float = 0.05,
|
|
46
|
+
) -> float:
|
|
47
|
+
if rng.random() < 0.5:
|
|
48
|
+
return rng.uniform(low, low + (high - low) * tail_pct)
|
|
49
|
+
else:
|
|
50
|
+
return rng.uniform(high - (high - low) * tail_pct, high)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@pf.tracer.primitive(allow_exec=True)
|
|
54
|
+
def clip_gaussian(
|
|
55
|
+
rng: np.random.Generator,
|
|
56
|
+
mean: float,
|
|
57
|
+
std: float,
|
|
58
|
+
low: float | None = None,
|
|
59
|
+
high: float | None = None,
|
|
60
|
+
max_tries: int = 20,
|
|
61
|
+
) -> float:
|
|
62
|
+
low = low or mean - 3 * std
|
|
63
|
+
high = high or mean + 3 * std
|
|
64
|
+
|
|
65
|
+
for _ in range(max_tries):
|
|
66
|
+
val = rng.normal(mean, std)
|
|
67
|
+
if low <= val and val <= high:
|
|
68
|
+
return val
|
|
69
|
+
|
|
70
|
+
raise ValueError(
|
|
71
|
+
f"clip_gaussian({mean=}, {std=}, {low=}, {high=}) failed to "
|
|
72
|
+
f"sample a value in the range after {max_tries=}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def wrap_gaussian(
|
|
77
|
+
rng: np.random.Generator,
|
|
78
|
+
mean: float,
|
|
79
|
+
std: float,
|
|
80
|
+
low: float,
|
|
81
|
+
high: float,
|
|
82
|
+
):
|
|
83
|
+
x = rng.normal(mean, std)
|
|
84
|
+
|
|
85
|
+
if x < low:
|
|
86
|
+
x = high - (low - x) % (high - low)
|
|
87
|
+
elif x > high:
|
|
88
|
+
x = low + (x - high) % (high - low)
|
|
89
|
+
|
|
90
|
+
return x
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def exponential(
|
|
94
|
+
rng: np.random.Generator,
|
|
95
|
+
scale: float,
|
|
96
|
+
) -> float:
|
|
97
|
+
return rng.exponential(scale)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def log_uniform(
|
|
101
|
+
rng: np.random.Generator,
|
|
102
|
+
low: float,
|
|
103
|
+
high: float,
|
|
104
|
+
size: tuple | None = None,
|
|
105
|
+
) -> float:
|
|
106
|
+
return np.exp(rng.uniform(np.log(low), np.log(high), size=size))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def log_normal(
|
|
110
|
+
rng: np.random.Generator,
|
|
111
|
+
mean: float,
|
|
112
|
+
std: float,
|
|
113
|
+
size: tuple | None = None,
|
|
114
|
+
) -> float:
|
|
115
|
+
return np.exp(rng.normal(np.log(mean), std, size=size))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def spherical_sample(
|
|
119
|
+
rng: np.random.Generator,
|
|
120
|
+
min_elevation: float | None = None,
|
|
121
|
+
max_elevation: float | None = None,
|
|
122
|
+
retries: int = 100,
|
|
123
|
+
) -> float:
|
|
124
|
+
for _ in range(retries):
|
|
125
|
+
P = rng.standard_normal(3)
|
|
126
|
+
x = np.arctan2(np.abs(P[2]), (P[0] ** 2 + P[1] ** 2) ** 0.5)
|
|
127
|
+
if (min_elevation is None or x > np.radians(min_elevation)) and (
|
|
128
|
+
max_elevation is None or x < np.radians(max_elevation)
|
|
129
|
+
):
|
|
130
|
+
return np.degrees(x)
|
|
131
|
+
|
|
132
|
+
raise ValueError(
|
|
133
|
+
f"spherical_sample({min_elevation=}, {max_elevation=}) failed to "
|
|
134
|
+
f"sample a value in the range after {retries=}"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def mixture_of_gaussian(
|
|
139
|
+
rng: np.random.Generator,
|
|
140
|
+
means: np.ndarray,
|
|
141
|
+
stds: np.ndarray,
|
|
142
|
+
weights: list[float],
|
|
143
|
+
low: np.ndarray | float | None = None,
|
|
144
|
+
high: np.ndarray | float | None = None,
|
|
145
|
+
):
|
|
146
|
+
p = np.array(weights) / np.sum(weights)
|
|
147
|
+
idx = rng.choice(len(p), p=p)
|
|
148
|
+
|
|
149
|
+
mu = means[idx]
|
|
150
|
+
std = stds[idx]
|
|
151
|
+
|
|
152
|
+
res = rng.normal(mu, std)
|
|
153
|
+
|
|
154
|
+
if low is not None:
|
|
155
|
+
res = np.maximum(res, low)
|
|
156
|
+
if high is not None:
|
|
157
|
+
res = np.minimum(res, high)
|
|
158
|
+
|
|
159
|
+
return res
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def beta(
|
|
163
|
+
rng: np.random.Generator,
|
|
164
|
+
a: float,
|
|
165
|
+
b: float,
|
|
166
|
+
) -> float:
|
|
167
|
+
return rng.beta(a, b)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def poisson(
|
|
171
|
+
rng: np.random.Generator,
|
|
172
|
+
lam: float,
|
|
173
|
+
) -> float:
|
|
174
|
+
return rng.poisson(lam)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def triangular(
|
|
178
|
+
rng: np.random.Generator,
|
|
179
|
+
low: float,
|
|
180
|
+
high: float,
|
|
181
|
+
mode: float,
|
|
182
|
+
) -> float:
|
|
183
|
+
return rng.triangular(low, mode, high)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def gamma(
|
|
187
|
+
rng: np.random.Generator,
|
|
188
|
+
shape: float,
|
|
189
|
+
scale: float,
|
|
190
|
+
) -> float:
|
|
191
|
+
return rng.gamma(shape, scale)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def binomial(
|
|
195
|
+
rng: np.random.Generator,
|
|
196
|
+
n: int,
|
|
197
|
+
p: float,
|
|
198
|
+
) -> float:
|
|
199
|
+
return rng.binomial(n, p)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def geometric(
|
|
203
|
+
rng: np.random.Generator,
|
|
204
|
+
p: float,
|
|
205
|
+
) -> float:
|
|
206
|
+
return rng.geometric(p)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
random_distrib_funcs = (
|
|
210
|
+
uniform,
|
|
211
|
+
normal,
|
|
212
|
+
uniform_tails,
|
|
213
|
+
clip_gaussian,
|
|
214
|
+
wrap_gaussian,
|
|
215
|
+
log_uniform,
|
|
216
|
+
log_normal,
|
|
217
|
+
spherical_sample,
|
|
218
|
+
mixture_of_gaussian,
|
|
219
|
+
beta,
|
|
220
|
+
poisson,
|
|
221
|
+
triangular,
|
|
222
|
+
gamma,
|
|
223
|
+
binomial,
|
|
224
|
+
geometric,
|
|
225
|
+
exponential,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
__all__ = [
|
|
230
|
+
"uniform",
|
|
231
|
+
"normal",
|
|
232
|
+
"uniform_tails",
|
|
233
|
+
"clip_gaussian",
|
|
234
|
+
"wrap_gaussian",
|
|
235
|
+
"log_uniform",
|
|
236
|
+
"log_normal",
|
|
237
|
+
"spherical_sample",
|
|
238
|
+
"mixture_of_gaussian",
|
|
239
|
+
"beta",
|
|
240
|
+
"poisson",
|
|
241
|
+
"triangular",
|
|
242
|
+
"gamma",
|
|
243
|
+
"binomial",
|
|
244
|
+
"geometric",
|
|
245
|
+
"exponential",
|
|
246
|
+
"random_distrib_funcs",
|
|
247
|
+
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from procfunc.tracer.decorator import (
|
|
2
|
+
generator,
|
|
3
|
+
grammar,
|
|
4
|
+
primitive,
|
|
5
|
+
random_control,
|
|
6
|
+
random_param,
|
|
7
|
+
register_trace_target,
|
|
8
|
+
)
|
|
9
|
+
from procfunc.tracer.patch import (
|
|
10
|
+
PATCHING_FLAG_ATTR,
|
|
11
|
+
Patcher,
|
|
12
|
+
PatchFunctionTarget,
|
|
13
|
+
TraceLevel,
|
|
14
|
+
)
|
|
15
|
+
from procfunc.tracer.proxy import (
|
|
16
|
+
RngProxy,
|
|
17
|
+
RngSpawnResultProxy,
|
|
18
|
+
)
|
|
19
|
+
from procfunc.tracer.trace import (
|
|
20
|
+
add_banned_module,
|
|
21
|
+
add_search_scope,
|
|
22
|
+
add_wrap_target,
|
|
23
|
+
autowrap_module,
|
|
24
|
+
trace,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"TraceLevel",
|
|
29
|
+
"grammar",
|
|
30
|
+
"random_control",
|
|
31
|
+
"random_param",
|
|
32
|
+
"generator",
|
|
33
|
+
"primitive",
|
|
34
|
+
"RngProxy",
|
|
35
|
+
"RngSpawnResultProxy",
|
|
36
|
+
"Patcher",
|
|
37
|
+
"PatchFunctionTarget",
|
|
38
|
+
"PATCHING_FLAG_ATTR",
|
|
39
|
+
"trace",
|
|
40
|
+
"add_banned_module",
|
|
41
|
+
"add_wrap_target",
|
|
42
|
+
"autowrap_module",
|
|
43
|
+
]
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import inspect
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Callable
|
|
5
|
+
|
|
6
|
+
from .patch import PatchFunctionTarget, TraceLevel
|
|
7
|
+
from .trace import add_wrap_target
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def register_trace_target(
|
|
13
|
+
func: Callable,
|
|
14
|
+
trace_level: TraceLevel,
|
|
15
|
+
allow_exec: bool,
|
|
16
|
+
custom_trace_wrapper_create: Callable | None,
|
|
17
|
+
mutates: list[str] | None = None,
|
|
18
|
+
normalize: bool = True,
|
|
19
|
+
):
|
|
20
|
+
"""Helper function to register a function for tracing with consistent frame inspection"""
|
|
21
|
+
|
|
22
|
+
if ".<locals>." in getattr(func, "__qualname__", ""):
|
|
23
|
+
raise ValueError(
|
|
24
|
+
f"Cannot register {func.__qualname__!r} as a trace target: local functions "
|
|
25
|
+
"(defined inside another function) are not in module globals and cannot be "
|
|
26
|
+
"traced. Move it to module level or remove the procfunc decorator."
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
f = inspect.currentframe()
|
|
30
|
+
while f.f_code.co_name != "<module>":
|
|
31
|
+
assert hasattr(f, "f_back")
|
|
32
|
+
f = f.f_back
|
|
33
|
+
assert hasattr(f, "f_code")
|
|
34
|
+
|
|
35
|
+
frame = f.f_globals
|
|
36
|
+
sourcename = f.f_code.co_filename.split("/")[-1][:-3] # remove .py
|
|
37
|
+
|
|
38
|
+
assert hasattr(func, "__name__")
|
|
39
|
+
assert isinstance(func.__name__, str)
|
|
40
|
+
|
|
41
|
+
# Local functions (defined inside another function) are never in the module
|
|
42
|
+
# globals frame, so registering them would leave a stale entry that causes
|
|
43
|
+
# KeyError on every subsequent pf.trace() call.
|
|
44
|
+
if ".<locals>." in getattr(func, "__qualname__", ""):
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
add_wrap_target(
|
|
48
|
+
PatchFunctionTarget(
|
|
49
|
+
frame=frame,
|
|
50
|
+
name=func.__name__,
|
|
51
|
+
trace_level=trace_level,
|
|
52
|
+
allow_exec=allow_exec,
|
|
53
|
+
custom_trace_wrapper_create=custom_trace_wrapper_create,
|
|
54
|
+
source_name=sourcename,
|
|
55
|
+
mutates=mutates,
|
|
56
|
+
normalize=normalize,
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _make_decorator(
|
|
62
|
+
trace_level: TraceLevel = TraceLevel.GENERATORS,
|
|
63
|
+
):
|
|
64
|
+
"""
|
|
65
|
+
Main decorator to mark a function and control its behaviour during tracing
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
trace_level: The level at which this function should be traced
|
|
69
|
+
allow_exec: If True, the function may be executed. Use False for any functions that create meshes or have side-effects
|
|
70
|
+
custom_trace_wrapper_create: Custom wrapper creation function for special tracing behavior
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
def decorator(
|
|
74
|
+
func: Callable | None = None,
|
|
75
|
+
*,
|
|
76
|
+
allow_exec: bool = False,
|
|
77
|
+
custom_trace_wrapper_create: Callable | None = None,
|
|
78
|
+
mutates: list[str] | None = None,
|
|
79
|
+
normalize: bool = True,
|
|
80
|
+
) -> Callable:
|
|
81
|
+
@functools.wraps(func)
|
|
82
|
+
def decorate(
|
|
83
|
+
func: Callable,
|
|
84
|
+
):
|
|
85
|
+
logger.debug(
|
|
86
|
+
f"Decorating {func.__name__} with {trace_level=} {custom_trace_wrapper_create=}"
|
|
87
|
+
)
|
|
88
|
+
# When called as decorator, we need to go back 2 frames
|
|
89
|
+
register_trace_target(
|
|
90
|
+
func,
|
|
91
|
+
trace_level,
|
|
92
|
+
allow_exec,
|
|
93
|
+
custom_trace_wrapper_create,
|
|
94
|
+
mutates=mutates,
|
|
95
|
+
normalize=normalize,
|
|
96
|
+
)
|
|
97
|
+
return func
|
|
98
|
+
|
|
99
|
+
# handle EITHER @decorator or @decorator(args)
|
|
100
|
+
if func is not None:
|
|
101
|
+
return decorate(func)
|
|
102
|
+
else:
|
|
103
|
+
return decorate
|
|
104
|
+
|
|
105
|
+
return decorator
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
grammar = _make_decorator(trace_level=TraceLevel.GRAMMAR)
|
|
109
|
+
random_control = _make_decorator(trace_level=TraceLevel.RANDOM_CONTROL)
|
|
110
|
+
random_param = _make_decorator(trace_level=TraceLevel.RANDOM_PARAMS)
|
|
111
|
+
generator = _make_decorator(trace_level=TraceLevel.GENERATORS)
|
|
112
|
+
primitive = _make_decorator(trace_level=TraceLevel.PRIMITIVES)
|
|
113
|
+
|
|
114
|
+
__all__ = [
|
|
115
|
+
"register_trace_target",
|
|
116
|
+
"grammar",
|
|
117
|
+
"random_control",
|
|
118
|
+
"random_param",
|
|
119
|
+
"generator",
|
|
120
|
+
"primitive",
|
|
121
|
+
]
|