Files
mcDandy-more_math/more_math/deprecated/ConditioningMathNode.py
T
mcDandy f6413f4202 Refactor math nodes and update documentation
Improved error messages in AudioMathNode and refactored ConditioningMathNode to simplify input handling and output structure. Updated README to clarify blur and edge function behaviors. Removed redundant 'category' field from deprecated node schemas to hide them.
2026-01-25 22:20:54 +01:00

107 lines
4.7 KiB
Python

from ..helper_functions import commonLazy,parse_expr, generate_dim_variables, as_tensor, prepare_inputs, getIndexTensorAlongDim, normalize_to_common_shape
from comfy_api.latest import io
import torch
from ..Parser.UnifiedMathVisitor import UnifiedMathVisitor
class ConditioningMathNodeOLD(io.ComfyNode):
"""
Enables math operations on conditionings.
Inputs:
a, b, c, d: Conditioning inputs (b, c, d default to zero if not provided)
w, x, y, z: Float variables for expressions
Tensor: Expression for the tensor part (describes image composition)
pooled_output: Expression for the pooled output (condensed representation)
Outputs:
CONDITIONING: Result of applying expressions to input conditionings
"""
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id="mrmth_ConditioningMathNode",
display_name="Conditioning math",
inputs=[
io.Conditioning.Input(id="a"),
io.Conditioning.Input(id="b", optional=True, lazy=True),
io.Conditioning.Input(id="c", optional=True, lazy=True),
io.Conditioning.Input(id="d", optional=True, lazy=True),
io.Float.Input(id="w", default=0.0, optional=True, lazy=True, force_input=True),
io.Float.Input(id="x", default=0.0, optional=True, lazy=True, force_input=True),
io.Float.Input(id="y", default=0.0, optional=True, lazy=True, force_input=True),
io.Float.Input(id="z", default=0.0, optional=True, lazy=True, force_input=True),
io.String.Input(id="Tensor", default="a*(1-w)+b*w", tooltip="Expression for tensor part (image composition)"),
io.String.Input(
id="pooled_output", default="a*(1-w)+b*w", tooltip="Expression for pooled output (condensed representation)"
),
io.Combo.Input(
id="length_mismatch",
options=["error", "error", "pad"],
default="error",
tooltip="How to handle mismatched conditioning segment counts. tile: repeat shorter inputs; error: raise error on mismatch; pad: treat missing as zero."
)
],
outputs=[
io.Conditioning.Output(),
],
)
@classmethod
def check_lazy_status(cls, Tensor, pooled_output, a, b=[], c=[], d=[], w=0, x=0, y=0, z=0, length_mismatch="tile"):
tensor_needs = set(commonLazy(Tensor, a, b, c, d, w, x, y, z))
pooled_needs = set(commonLazy(pooled_output, a, b, c, d, w, x, y, z))
return list(tensor_needs.union(pooled_needs))
@classmethod
def execute(cls, Tensor, pooled_output, a, b=None, c=None, d=None, w=0.0, x=0.0, y=0.0, z=0.0, length_mismatch="tile"):
# Default missing conditionings to zero
a_c, b_c, c_c, d_c = prepare_inputs(a, b, c, d)
# We process the first segment of each conditioning
ta_full, da = a_c[0]
tb_full, db = b_c[0]
tc_full, dc = c_c[0]
td_full, dd = d_c[0]
ta, tb, tc, td = normalize_to_common_shape(ta_full, tb_full, tc_full, td_full, mode=length_mismatch)
B_val = getIndexTensorAlongDim(ta, 0)
variables = {
"a": ta, "b": tb, "c": tc, "d": td, "w": w, "x": x, "y": y, "z": z,
"B": B_val, "batch": B_val,
"T": ta.shape[0], "batch_count": ta.shape[0],
"N": ta.shape[1], "channel_count": ta.shape[1],
} | generate_dim_variables(ta)
tree = parse_expr(Tensor)
visitor = UnifiedMathVisitor(variables, ta.shape)
result_tensor = as_tensor(visitor.visit(tree), ta.shape)
new_dict = da.copy()
pa = da.get("pooled_output")
if pa is not None:
pb = db.get("pooled_output")
pc = dc.get("pooled_output")
pd = dd.get("pooled_output")
pb = pb if pb is not None else torch.zeros_like(pa)
pc = pc if pc is not None else torch.zeros_like(pa)
pd = pd if pd is not None else torch.zeros_like(pa)
pa, pb, pc, pd = normalize_to_common_shape(pa, pb, pc, pd, mode=length_mismatch)
variables_pooled = {"a": pa, "b": pb, "c": pc, "d": pd, "w": w, "x": x, "y": y, "z": z} | generate_dim_variables(pa)
tree_p = parse_expr(pooled_output)
visitor_p = UnifiedMathVisitor(variables_pooled, pa.shape)
result_pooled = as_tensor(visitor_p.visit(tree_p), pa.shape)
new_dict["pooled_output"] = result_pooled
# Create new conditioning list
output_cond = [(result_tensor, new_dict)]
if len(a) > 1:
output_cond.extend(a[1:])
return (output_cond,)