Add files via upload
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
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)",
|
||||
}
|
||||
Reference in New Issue
Block a user