-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathoutput_any_debug_data_node.py
More file actions
124 lines (103 loc) · 5.03 KB
/
Copy pathoutput_any_debug_data_node.py
File metadata and controls
124 lines (103 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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)",
}