dikdimon commited on
Commit
37b6731
·
verified ·
1 Parent(s): 1ac20ad

Delete xyz_grid.py

Browse files
Files changed (1) hide show
  1. xyz_grid.py +0 -285
xyz_grid.py DELETED
@@ -1,285 +0,0 @@
1
- """
2
- lib_mega_freeu/global_state.py
3
- Runtime state, data structures, presets for ⚡ Mega FreeU.
4
-
5
- Sources:
6
- sd-webui-freeu/lib_free_u/global_state.py -- StageInfo layout, State, preset JSON, XYZ
7
- WAS FreeU_Advanced/nodes.py -- BLEND_MODE_NAMES, MSCALES
8
- ComfyUI_FreeU_V2_Advanced/FreeU_B1B2.py -- b_start/b_end, channel_threshold
9
- ComfyUI_FreeU_V2_Advanced/FreeU_S1S2.py -- s_start/s_end, adaptive cap
10
- nrs_kohaku_enhanced_v3_5.py -- hf_boost, gaussian standalone
11
- """
12
- import dataclasses
13
- import json
14
- import math
15
- import pathlib
16
- import re
17
- import sys
18
- from typing import Any, Dict, List, Optional, Union
19
-
20
- # ─── Blending modes (WAS FreeU_Advanced/nodes.py blending_modes keys) ─────────
21
- BLEND_MODE_NAMES: List[str] = [
22
- "lerp", "inject", "bislerp", "colorize",
23
- "cosine interp", "cuberp", "hslerp", "stable_slerp", "linear dodge",
24
- ]
25
-
26
- # ─── Multi-scale presets (WAS nodes.py mscales dict -- exact) ─────────────────
27
- MSCALES: Dict[str, Optional[list]] = {
28
- "Default": None,
29
- "Low-Pass": [(10, 1.0)],
30
- "Pass-Through": [(10, 1.0)],
31
- "Gaussian-Blur": [(10, 0.5)],
32
- "Edge-Enhancement": [(10, 2.0)],
33
- "Sharpen": [(10, 1.5)],
34
- "Multi-Bandpass": [[(5, 0.0), (15, 1.0), (25, 0.0)]],
35
- "Multi-Low-Pass": [[(5, 1.0), (10, 0.5), (15, 0.2)]],
36
- "Multi-High-Pass": [[(5, 0.0), (10, 0.5), (15, 0.8)]],
37
- "Multi-Pass-Through": [[(5, 1.0), (10, 1.0), (15, 1.0)]],
38
- "Multi-Gaussian-Blur": [[(5, 0.5), (10, 0.8), (15, 0.2)]],
39
- "Multi-Edge-Enhancement": [[(5, 1.2), (10, 1.5), (15, 2.0)]],
40
- "Multi-Sharpen": [[(5, 1.5), (10, 2.0), (15, 2.5)]],
41
- }
42
-
43
- ALL_VERSIONS: Dict[str, str] = {"Version 1": "1", "Version 2": "2"}
44
- REVERSED_VERSIONS: Dict[str, str] = {v: k for k, v in ALL_VERSIONS.items()}
45
- FFT_TYPES: List[str] = ["gaussian", "box"]
46
- STAGES_COUNT: int = 3
47
-
48
- _shorthand_re = re.compile(r"^([a-z]{1,3})(\d+)$")
49
-
50
- # ─── StageInfo ─────────────────────────────────────────────────────────────────
51
- @dataclasses.dataclass
52
- class StageInfo:
53
- """
54
- All per-stage parameters.
55
- Fields 1-6: same order as sd-webui-freeu for PNG backwards compat.
56
- New fields appended at end.
57
- """
58
- # sd-webui-freeu compat (DO NOT REORDER first 6)
59
- backbone_factor: float = 1.0
60
- skip_factor: float = 1.0
61
- backbone_offset: float = 0.0
62
- backbone_width: float = 0.5
63
- skip_cutoff: float = 0.0
64
- skip_high_end_factor: float = 1.0
65
- # WAS blending
66
- backbone_blend_mode: str = "lerp"
67
- backbone_blend: float = 1.0
68
- # ComfyUI V2 independent timestep ranges
69
- b_start_ratio: float = 0.0
70
- b_end_ratio: float = 1.0
71
- s_start_ratio: float = 0.0
72
- s_end_ratio: float = 1.0
73
- # FFT
74
- fft_type: str = "box"
75
- fft_radius_ratio: float = 0.07
76
- hf_boost: float = 1.0
77
- # Adaptive Cap (FreeU_S1S2)
78
- enable_adaptive_cap: bool = False
79
- cap_threshold: float = 0.35
80
- cap_factor: float = 0.6
81
- adaptive_cap_mode: str = "adaptive"
82
-
83
- def to_dict(self, include_default=False):
84
- default = StageInfo()
85
- d = dataclasses.asdict(self)
86
- if not include_default:
87
- d = {k: v for k, v in d.items() if v != getattr(default, k)}
88
- return d
89
-
90
- def copy(self):
91
- return StageInfo(**dataclasses.asdict(self))
92
-
93
- STAGE_FIELD_NAMES = [f.name for f in dataclasses.fields(StageInfo)]
94
- STAGE_FIELD_COUNT = len(STAGE_FIELD_NAMES)
95
-
96
- # ─── State ─────────────────────────────────────────────────────────────────────
97
- @dataclasses.dataclass
98
- class State:
99
- enable: bool = True
100
- start_ratio: Any = 0.0
101
- stop_ratio: Any = 1.0
102
- transition_smoothness: float = 0.0
103
- version: str = "1"
104
- multiscale_mode: str = "Default"
105
- multiscale_strength: float = 1.0
106
- override_scales: str = ""
107
- channel_threshold: int = 96
108
- stage_infos: List[Any] = dataclasses.field(
109
- default_factory=lambda: [StageInfo() for _ in range(STAGES_COUNT)]
110
- )
111
- # Post-CFG Shift (WAS_PostCFGShift) — stored in presets & PNG
112
- pcfg_enabled: bool = False
113
- pcfg_steps: int = 20
114
- pcfg_mode: str = "inject"
115
- pcfg_blend: float = 1.0
116
- pcfg_b: float = 1.1
117
- pcfg_fourier: bool = False
118
- pcfg_ms_mode: str = "Default"
119
- pcfg_ms_str: float = 1.0
120
- pcfg_threshold: int = 1
121
- pcfg_s: float = 0.5
122
- pcfg_gain: float = 1.0
123
- verbose: bool = False
124
-
125
- def __post_init__(self):
126
- self.stage_infos = self._coerce_stages()
127
- self.version = ALL_VERSIONS.get(self.version, self.version)
128
-
129
- def _coerce_stages(self):
130
- result, raw = [], list(self.stage_infos)
131
- i = 0
132
- while i < len(raw) and len(result) < STAGES_COUNT:
133
- item = raw[i]
134
- if isinstance(item, StageInfo):
135
- result.append(item); i += 1
136
- elif isinstance(item, dict):
137
- known = {k: v for k, v in item.items() if k in STAGE_FIELD_NAMES}
138
- result.append(StageInfo(**known)); i += 1
139
- else:
140
- chunk = raw[i:i+STAGE_FIELD_COUNT]
141
- result.append(StageInfo(*chunk))
142
- i += STAGE_FIELD_COUNT
143
- while len(result) < STAGES_COUNT:
144
- result.append(StageInfo())
145
- return result
146
-
147
- def to_dict(self):
148
- d = dataclasses.asdict(self)
149
- d["stage_infos"] = [si.to_dict() for si in self.stage_infos]
150
- del d["enable"]
151
- return d
152
-
153
- def copy(self):
154
- d = dataclasses.asdict(self)
155
- d["stage_infos"] = [StageInfo(**s) for s in d["stage_infos"]]
156
- return State(**d)
157
-
158
- def update_attr(self, key, value):
159
- if m := _shorthand_re.match(key):
160
- char, idx = m.group(1), int(m.group(2))
161
- if 0 <= idx < STAGES_COUNT:
162
- si = self.stage_infos[idx]
163
- _MAP = {
164
- "b":"backbone_factor","s":"skip_factor","o":"backbone_offset",
165
- "w":"backbone_width","t":"skip_cutoff","h":"skip_high_end_factor",
166
- "bm":"backbone_blend_mode","bb":"backbone_blend",
167
- "bs":"b_start_ratio","be":"b_end_ratio",
168
- "ss":"s_start_ratio","se":"s_end_ratio",
169
- "ft":"fft_type","fr":"fft_radius_ratio","hfb":"hf_boost",
170
- "cap":"enable_adaptive_cap","ct":"cap_threshold","cf":"cap_factor","acm":"adaptive_cap_mode",
171
- }
172
- if char in _MAP:
173
- setattr(si, _MAP[char], value); return
174
- if hasattr(self, key):
175
- setattr(self, key, value)
176
-
177
- # ─── Singletons ────────────────────────────────────────────────────────────────
178
- instance: State = State()
179
- xyz_attrs: Dict[str, Any] = {}
180
- current_sampling_step: int = 0
181
-
182
- # ─── Preset builders ───────────────────────────────────────────────────────────
183
- def _v1(*pairs):
184
- infos = [StageInfo(backbone_factor=b, skip_factor=s) for b,s in pairs]
185
- while len(infos) < STAGES_COUNT: infos.append(StageInfo())
186
- return State(version="1", stage_infos=infos)
187
-
188
- def _v2g(pairs):
189
- infos = []
190
- for b, s, r, hfb, bs, be, ss, se in pairs:
191
- infos.append(StageInfo(
192
- backbone_factor=b, skip_factor=s,
193
- fft_type="gaussian", fft_radius_ratio=r, hf_boost=hfb,
194
- b_start_ratio=bs, b_end_ratio=be,
195
- s_start_ratio=ss, s_end_ratio=se,
196
- ))
197
- while len(infos) < STAGES_COUNT: infos.append(StageInfo())
198
- return State(version="2", stage_infos=infos)
199
-
200
- default_presets: Dict[str, State] = {
201
- "SD1.4 Recommendations": _v1((1.2,0.9),(1.4,0.2),(1.0,1.0)),
202
- "SD2.1 Recommendations": _v1((1.1,0.9),(1.2,0.2),(1.0,1.0)),
203
- "SDXL Recommendations": _v1((1.1,0.6),(1.2,0.4),(1.0,1.0)),
204
- "SD1.5 V2 Gaussian": _v2g([
205
- (1.2,0.9,0.07,1.0, 0.0,0.35, 0.35,1.0),
206
- (1.4,0.2,0.07,1.0, 0.0,0.35, 0.35,1.0),
207
- ]),
208
- "SD1.5 V2 High Detail": _v2g([
209
- (1.4,0.8,0.08,1.2, 0.0,0.35, 0.35,1.0),
210
- (1.6,0.1,0.06,1.0, 0.0,0.35, 0.35,1.0),
211
- ]),
212
- "SDXL V2 Gaussian": _v2g([
213
- (1.1,0.6,0.05,1.1, 0.0,0.35, 0.35,1.0),
214
- (1.2,0.4,0.05,1.1, 0.0,0.35, 0.35,1.0),
215
- ]),
216
- "SD1.5 Adaptive Cap": State(version="2", stage_infos=[
217
- StageInfo(backbone_factor=1.3,skip_factor=0.9,
218
- fft_type="gaussian",fft_radius_ratio=0.08,hf_boost=1.2,
219
- b_start_ratio=0.0,b_end_ratio=0.35,
220
- s_start_ratio=0.35,s_end_ratio=1.0,
221
- enable_adaptive_cap=True,cap_threshold=0.35,
222
- cap_factor=0.6,adaptive_cap_mode="adaptive"),
223
- StageInfo(backbone_factor=1.4,skip_factor=0.2,
224
- fft_type="gaussian",fft_radius_ratio=0.06,hf_boost=1.0,
225
- b_start_ratio=0.0,b_end_ratio=0.35,
226
- s_start_ratio=0.35,s_end_ratio=1.0,
227
- enable_adaptive_cap=True,cap_threshold=0.70,
228
- cap_factor=0.6,adaptive_cap_mode="adaptive"),
229
- StageInfo(),
230
- ]),
231
- "Independent B/S (SD1.5)": _v2g([
232
- (1.2,0.9,0.07,1.0, 0.0,0.35, 0.35,1.0),
233
- (1.4,0.2,0.06,1.0, 0.0,0.35, 0.35,1.0),
234
- ]),
235
- }
236
-
237
- all_presets: Dict[str, State] = {}
238
- PRESETS_PATH = pathlib.Path(__file__).parent.parent / "presets.json"
239
-
240
- def reload_presets():
241
- all_presets.clear()
242
- all_presets.update(default_presets)
243
- all_presets.update(_load_user_presets())
244
-
245
- def _load_user_presets():
246
- if not PRESETS_PATH.exists(): return {}
247
- try:
248
- with open(PRESETS_PATH, encoding="utf-8") as f:
249
- raw = json.load(f)
250
- except Exception as e:
251
- print(f"[MegaFreeU] preset load error: {e}", file=sys.stderr)
252
- return {}
253
- result = {}
254
- _state_fields = {f.name for f in dataclasses.fields(State)}
255
- for k, v in raw.items():
256
- try:
257
- # Filter unknown keys so future/old fields don't crash State(**v)
258
- known = {fk: fv for fk, fv in v.items() if fk in _state_fields}
259
- result[k] = State(**known)
260
- except Exception as e:
261
- print(f"[MegaFreeU] skipping preset {k!r}: {e}", file=sys.stderr)
262
- return result
263
-
264
- def save_presets(custom=None):
265
- if custom is None: custom = get_user_presets()
266
- try:
267
- PRESETS_PATH.parent.mkdir(parents=True, exist_ok=True)
268
- with open(PRESETS_PATH, "w", encoding="utf-8") as f:
269
- json.dump({k: v.to_dict() for k,v in custom.items()}, f, indent=4)
270
- except Exception as e:
271
- print(f"[MegaFreeU] preset save error: {e}", file=sys.stderr)
272
-
273
- def get_user_presets():
274
- return {k: v for k,v in all_presets.items() if k not in default_presets}
275
-
276
- def apply_xyz():
277
- global instance
278
- if pk := xyz_attrs.get("preset"):
279
- if p := all_presets.get(pk):
280
- instance = p.copy()
281
- elif pk != "UI Settings":
282
- print(f"[MegaFreeU] XYZ preset '{pk}' not found", file=sys.stderr)
283
- for k, v in xyz_attrs.items():
284
- if k != "preset":
285
- instance.update_attr(k, v)