124 lines
5.0 KiB
Python
124 lines
5.0 KiB
Python
import torch
|
|
|
|
# Special AnyType to allow any connection
|
|
class AnyType(str):
|
|
def __ne__(self, __value: object) -> bool:
|
|
return False
|
|
|
|
any_type = AnyType("*")
|
|
|
|
class OutputAnyDebugDataNode:
|
|
"""
|
|
A debug node that accepts ANY input and analyzes it.
|
|
- If IMAGE: Shows resolution (WxH), Aspect Ratio, and Batch Size.
|
|
- If LATENT: Shows Latent Dimensions and equivalent Pixel Resolution (8x).
|
|
- If other: Shows Type and raw string representation.
|
|
|
|
The result is displayed as text on the node itself (via JS) and output as a string.
|
|
"""
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"any_input": (any_type,),
|
|
},
|
|
"hidden": {
|
|
"unique_id": "UNIQUE_ID",
|
|
"extra_pnginfo": "EXTRA_PNGINFO",
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("debug_text",)
|
|
FUNCTION = "analyze_data"
|
|
CATEGORY = "flow-assistor/debug"
|
|
OUTPUT_NODE = True
|
|
|
|
def analyze_data(self, any_input, unique_id=None, extra_pnginfo=None):
|
|
text_output = "None"
|
|
|
|
try:
|
|
# 1. Handle Torch Tensors (Images, Masks, Raw Latents)
|
|
if isinstance(any_input, torch.Tensor):
|
|
shape = any_input.shape
|
|
# Basic info
|
|
text_output = f"Type: Tensor\nShape: {list(shape)}\nDtype: {any_input.dtype}\nDevice: {any_input.device}\n"
|
|
|
|
# Heuristic for IMAGE: [Batch, Height, Width, Channels]
|
|
if any_input.ndim == 4:
|
|
# Standard Image: Channels at end (usually 3 or 4)
|
|
if shape[3] <= 4 and shape[1] > 8 and shape[2] > 8:
|
|
b, h, w, c = shape
|
|
ar = w / h if h > 0 else 0
|
|
text_output += f"\n--- IMAGE DETECTED ---\n"
|
|
text_output += f"Resolution: {w}x{h}\n"
|
|
text_output += f"Aspect Ratio: {ar:.2f}\n"
|
|
text_output += f"Batch Size: {b}\n"
|
|
text_output += f"Channels: {c}"
|
|
|
|
# Raw Latent / NCHW: Channels at dim 1
|
|
elif shape[1] <= 4 and shape[2] > 8 and shape[3] > 8:
|
|
b, c, h, w = shape
|
|
text_output += f"\n--- RAW LATENT/NCHW ---\n"
|
|
text_output += f"Latent Size: {w}x{h}\n"
|
|
text_output += f"Pixel Res (~8x): {w*8}x{h*8}\n"
|
|
text_output += f"Batch Size: {b}"
|
|
|
|
# Heuristic for MASK: [Batch, Height, Width]
|
|
elif any_input.ndim == 3:
|
|
b, h, w = shape
|
|
text_output += f"\n--- MASK DETECTED ---\n"
|
|
text_output += f"Resolution: {w}x{h}\n"
|
|
text_output += f"Batch Size: {b}"
|
|
|
|
# 2. Handle Latent Dictionary (Standard ComfyUI Latent Wrapper)
|
|
elif isinstance(any_input, dict) and "samples" in any_input:
|
|
samples = any_input["samples"]
|
|
if isinstance(samples, torch.Tensor):
|
|
# Shape: [Batch, 4, Height, Width]
|
|
shape = samples.shape
|
|
b, c, h, w = shape
|
|
ar = w / h if h > 0 else 0
|
|
|
|
text_output = f"Type: LATENT (Dict)\nShape: {list(shape)}\n"
|
|
text_output += f"\n--- RESOLUTION INFO ---\n"
|
|
text_output += f"Latent Size: {w}x{h}\n"
|
|
text_output += f"Pixel Res (8x): {w*8}x{h*8}\n"
|
|
text_output += f"Aspect Ratio: {ar:.2f}\n"
|
|
text_output += f"Batch Size: {b}"
|
|
else:
|
|
text_output = f"Type: LATENT (Dict)\nError: 'samples' is not a tensor."
|
|
|
|
# 3. Handle Lists
|
|
elif isinstance(any_input, list):
|
|
text_output = f"Type: List\nLength: {len(any_input)}\n"
|
|
if len(any_input) > 0:
|
|
text_output += f"Sample[0]: {str(any_input[0])[:50]}..."
|
|
|
|
# 4. Handle Basic Types
|
|
elif isinstance(any_input, (int, float, bool, str)):
|
|
text_output = f"Type: {type(any_input).__name__}\nValue: {any_input}"
|
|
|
|
# 5. Generic Fallback
|
|
else:
|
|
raw_str = str(any_input)
|
|
text_output = f"Type: {type(any_input)}\n"
|
|
text_output += f"Value: {raw_str[:200]}..." if len(raw_str) > 0 else "Empty"
|
|
|
|
except Exception as e:
|
|
text_output = f"Error analyzing data: {str(e)}"
|
|
|
|
# Return: {"ui": {KEY: [LIST]}, "result": (TUPLE)}
|
|
return {"ui": {"text": [text_output]}, "result": (text_output,)}
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"OutputAnyDebugDataNode": OutputAnyDebugDataNode,
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"OutputAnyDebugDataNode": "Debug Data (Any Input)",
|
|
} |