Critical:
- rename nodes/ -> mp_nodes/, shared/ -> mp_shared/ to avoid shadowing
ComfyUI core's nodes.py via sys.path injection (root cause of v0.1.1
'nodes is not a package' startup failure)
- http_post now streams response and enforces 50MB cap mid-stream (DoS)
- AES key derivation: HKDF -> PBKDF2-HMAC-SHA256 600k iters + random salt
(work factor against weak-key brute force; ciphertext format changed)
- fs_mkdir/copy/move/delete confined to ComfyUI input/output/temp + ~ by
default; UTILITY_MEGAPACK_ALLOW_ARBITRARY_PATHS=1 to override
UX / correctness:
- combo settings now declare options array (themes dropdown was empty)
- LATENT default 1x4x8x8 zeros -> {} (avoids Flux/SD3 shape crashes)
- @op decorator rejects reserved widget names mode/theme at register time
- _pad_outputs docstring updated to match relaxed opaque-type behavior
153 lines
3.7 KiB
Python
153 lines
3.7 KiB
Python
"""Math, statistics, and randomness."""
|
|
|
|
import random
|
|
import statistics
|
|
|
|
from .. import op
|
|
|
|
|
|
@op(
|
|
op_id="math_add",
|
|
display_name="Math Add",
|
|
category="Math & Signals",
|
|
input_schema={"required": {
|
|
"a": ("FLOAT", {"default": 0.0}),
|
|
"b": ("FLOAT", {"default": 0.0}),
|
|
}},
|
|
output_indices=(2,),
|
|
)
|
|
def math_add(self, a, b):
|
|
return (float(a) + float(b),)
|
|
|
|
|
|
@op(
|
|
op_id="math_subtract",
|
|
display_name="Math Subtract",
|
|
category="Math & Signals",
|
|
input_schema={"required": {
|
|
"a": ("FLOAT", {"default": 0.0}),
|
|
"b": ("FLOAT", {"default": 0.0}),
|
|
}},
|
|
output_indices=(2,),
|
|
)
|
|
def math_subtract(self, a, b):
|
|
return (float(a) - float(b),)
|
|
|
|
|
|
@op(
|
|
op_id="math_multiply",
|
|
display_name="Math Multiply",
|
|
category="Math & Signals",
|
|
input_schema={"required": {
|
|
"a": ("FLOAT", {"default": 0.0}),
|
|
"b": ("FLOAT", {"default": 0.0}),
|
|
}},
|
|
output_indices=(2,),
|
|
)
|
|
def math_multiply(self, a, b):
|
|
return (float(a) * float(b),)
|
|
|
|
|
|
@op(
|
|
op_id="math_divide",
|
|
display_name="Math Divide",
|
|
category="Math & Signals",
|
|
input_schema={"required": {
|
|
"a": ("FLOAT", {"default": 0.0}),
|
|
"b": ("FLOAT", {"default": 1.0}),
|
|
}},
|
|
output_indices=(2,),
|
|
description="Raises ZeroDivisionError when b == 0.",
|
|
)
|
|
def math_divide(self, a, b):
|
|
if b == 0:
|
|
raise ZeroDivisionError("division by zero")
|
|
return (float(a) / float(b),)
|
|
|
|
|
|
@op(
|
|
op_id="math_clamp",
|
|
display_name="Math Clamp",
|
|
category="Math & Signals",
|
|
input_schema={"required": {
|
|
"value": ("FLOAT", {"default": 0.0}),
|
|
"lo": ("FLOAT", {"default": 0.0}),
|
|
"hi": ("FLOAT", {"default": 1.0}),
|
|
}},
|
|
output_indices=(2,),
|
|
)
|
|
def math_clamp(self, value, lo, hi):
|
|
return (float(max(lo, min(hi, value))),)
|
|
|
|
|
|
@op(
|
|
op_id="math_lerp",
|
|
display_name="Math Lerp",
|
|
category="Math & Signals",
|
|
input_schema={"required": {
|
|
"a": ("FLOAT", {"default": 0.0}),
|
|
"b": ("FLOAT", {"default": 1.0}),
|
|
"t": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0}),
|
|
}},
|
|
output_indices=(2,),
|
|
)
|
|
def math_lerp(self, a, b, t):
|
|
return (float(a) + (float(b) - float(a)) * float(t),)
|
|
|
|
|
|
@op(
|
|
op_id="stats_mean",
|
|
display_name="Stats Mean",
|
|
category="Math & Signals",
|
|
input_schema={"required": {"values": ("LIST", {"default": []})}},
|
|
output_indices=(2,),
|
|
)
|
|
def stats_mean(self, values):
|
|
if not values:
|
|
return (0.0,)
|
|
return (float(statistics.fmean(values)),)
|
|
|
|
|
|
@op(
|
|
op_id="stats_median",
|
|
display_name="Stats Median",
|
|
category="Math & Signals",
|
|
input_schema={"required": {"values": ("LIST", {"default": []})}},
|
|
output_indices=(2,),
|
|
)
|
|
def stats_median(self, values):
|
|
if not values:
|
|
return (0.0,)
|
|
return (float(statistics.median(values)),)
|
|
|
|
|
|
@op(
|
|
op_id="stats_std",
|
|
display_name="Stats Stdev (population)",
|
|
category="Math & Signals",
|
|
input_schema={"required": {"values": ("LIST", {"default": []})}},
|
|
output_indices=(2,),
|
|
description="Population standard deviation. Returns 0 for fewer than 2 values.",
|
|
)
|
|
def stats_std(self, values):
|
|
if not values or len(values) < 2:
|
|
return (0.0,)
|
|
return (float(statistics.pstdev(values)),)
|
|
|
|
|
|
@op(
|
|
op_id="random_uniform",
|
|
display_name="Random Uniform",
|
|
category="Math & Signals",
|
|
input_schema={"required": {
|
|
"lo": ("FLOAT", {"default": 0.0}),
|
|
"hi": ("FLOAT", {"default": 1.0}),
|
|
"seed": ("INT", {"default": -1, "min": -1, "max": 0xFFFFFFFF}),
|
|
}},
|
|
output_indices=(2,),
|
|
description="seed = -1 means non-deterministic; otherwise reproducible.",
|
|
)
|
|
def random_uniform(self, lo, hi, seed=-1):
|
|
rng = random.Random() if seed == -1 else random.Random(seed)
|
|
return (rng.uniform(float(lo), float(hi)),)
|