dinkster-api 0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. dinkster_api/__init__.py +9 -0
  2. dinkster_api/py.typed +0 -0
  3. dinkster_api/v1.py +935 -0
  4. dinkster_api-0.0.2.dist-info/METADATA +16 -0
  5. dinkster_api-0.0.2.dist-info/RECORD +238 -0
  6. dinkster_api-0.0.2.dist-info/WHEEL +4 -0
  7. dinkster_api-0.0.2.dist-info/entry_points.txt +2 -0
  8. dinkster_assets/__init__.py +337 -0
  9. dinkster_assets/acquire.py +226 -0
  10. dinkster_assets/acquisition_plan.py +145 -0
  11. dinkster_assets/audio.py +119 -0
  12. dinkster_assets/catalog.py +156 -0
  13. dinkster_assets/component_manifest.py +110 -0
  14. dinkster_assets/declared.py +218 -0
  15. dinkster_assets/fetch.py +495 -0
  16. dinkster_assets/guess.py +136 -0
  17. dinkster_assets/identity.py +72 -0
  18. dinkster_assets/integrity.py +310 -0
  19. dinkster_assets/json_metadata.py +41 -0
  20. dinkster_assets/kind.py +52 -0
  21. dinkster_assets/latent_format.py +346 -0
  22. dinkster_assets/library.py +816 -0
  23. dinkster_assets/media.py +1385 -0
  24. dinkster_assets/migrations/env.py +38 -0
  25. dinkster_assets/migrations/script.py.mako +28 -0
  26. dinkster_assets/migrations/versions/0001_asset_records_create_asset_record_catalog.py +109 -0
  27. dinkster_assets/migrations/versions/0002_asset_observations.py +36 -0
  28. dinkster_assets/model.py +242 -0
  29. dinkster_assets/mounts.py +1278 -0
  30. dinkster_assets/need.py +168 -0
  31. dinkster_assets/pack_assets.py +217 -0
  32. dinkster_assets/probe.py +118 -0
  33. dinkster_assets/provenance.py +254 -0
  34. dinkster_assets/public_acquisition.py +424 -0
  35. dinkster_assets/py.typed +0 -0
  36. dinkster_assets/records.py +899 -0
  37. dinkster_assets/resolution.py +778 -0
  38. dinkster_assets/resolver_index.py +364 -0
  39. dinkster_assets/resolver_subscription.py +1149 -0
  40. dinkster_assets/save_target.py +139 -0
  41. dinkster_assets/schema.py +73 -0
  42. dinkster_assets/selections.py +256 -0
  43. dinkster_assets/transport.py +243 -0
  44. dinkster_assets/value.py +258 -0
  45. dinkster_assets/vault.py +276 -0
  46. dinkster_assets/writer.py +765 -0
  47. dinkster_caches/__init__.py +19 -0
  48. dinkster_caches/cas.py +310 -0
  49. dinkster_caches/disk.py +330 -0
  50. dinkster_caches/layered.py +150 -0
  51. dinkster_caches/memory.py +208 -0
  52. dinkster_caches/py.typed +0 -0
  53. dinkster_caches/wire.py +346 -0
  54. dinkster_image_document/__init__.py +39 -0
  55. dinkster_image_document/blend.py +264 -0
  56. dinkster_image_document/compat.py +211 -0
  57. dinkster_image_document/document.py +374 -0
  58. dinkster_image_document/format.py +569 -0
  59. dinkster_image_document/interchange.py +572 -0
  60. dinkster_image_document/py.typed +1 -0
  61. dinkster_image_document/render.py +455 -0
  62. dinkster_inference_wire/__init__.py +141 -0
  63. dinkster_inference_wire/camera_wire.py +127 -0
  64. dinkster_inference_wire/conditioning.py +752 -0
  65. dinkster_inference_wire/conditioning_wire.py +1143 -0
  66. dinkster_inference_wire/devices.py +285 -0
  67. dinkster_inference_wire/generation.py +446 -0
  68. dinkster_inference_wire/hook_values.py +168 -0
  69. dinkster_inference_wire/ic_lora_parameters.py +69 -0
  70. dinkster_inference_wire/latents.py +244 -0
  71. dinkster_inference_wire/media_wire.py +169 -0
  72. dinkster_inference_wire/openai_generation.py +1035 -0
  73. dinkster_inference_wire/pose_keypoint.py +83 -0
  74. dinkster_inference_wire/process.py +33 -0
  75. dinkster_inference_wire/py.typed +0 -0
  76. dinkster_inference_wire/registry.py +116 -0
  77. dinkster_inference_wire/sam3_wire.py +68 -0
  78. dinkster_inference_wire/sampling_wire.py +279 -0
  79. dinkster_inference_wire/sources.py +399 -0
  80. dinkster_inference_wire/spaces.py +344 -0
  81. dinkster_inference_wire/sparse.py +372 -0
  82. dinkster_inference_wire/splat_wire.py +23 -0
  83. dinkster_inference_wire/types.py +256 -0
  84. dinkster_inference_wire/vision_wire.py +53 -0
  85. dinkster_inference_wire/voxel_wire.py +72 -0
  86. dinkster_inference_wire/wan_wire.py +93 -0
  87. dinkster_inference_wire/weights.py +219 -0
  88. dinkster_memory/__init__.py +92 -0
  89. dinkster_memory/accelerator.py +96 -0
  90. dinkster_memory/budgets.py +96 -0
  91. dinkster_memory/details.py +91 -0
  92. dinkster_memory/governor.py +554 -0
  93. dinkster_memory/leases.py +176 -0
  94. dinkster_memory/py.typed +0 -0
  95. dinkster_memory/release.py +131 -0
  96. dinkster_memory/reported.py +101 -0
  97. dinkster_memory/reservations.py +101 -0
  98. dinkster_memory/resident.py +600 -0
  99. dinkster_memory/system.py +614 -0
  100. dinkster_memory/tenants.py +67 -0
  101. dinkster_protocol/__init__.py +1008 -0
  102. dinkster_protocol/attention.py +652 -0
  103. dinkster_protocol/extension_contribution_kinds.json +21 -0
  104. dinkster_protocol/extension_contribution_kinds.py +43 -0
  105. dinkster_protocol/extensions.py +742 -0
  106. dinkster_protocol/frontend_modules.py +145 -0
  107. dinkster_protocol/multigpu.py +107 -0
  108. dinkster_protocol/pack_surfaces.py +489 -0
  109. dinkster_protocol/payload.py +63 -0
  110. dinkster_protocol/preview.py +86 -0
  111. dinkster_protocol/py.typed +0 -0
  112. dinkster_protocol/result_algebra.py +380 -0
  113. dinkster_protocol/result_document.py +244 -0
  114. dinkster_protocol/run_control.py +96 -0
  115. dinkster_protocol/training.py +399 -0
  116. dinkster_protocol/workgroup.py +1014 -0
  117. dinkster_registry/__init__.py +135 -0
  118. dinkster_registry/admission.py +372 -0
  119. dinkster_registry/artifact.py +128 -0
  120. dinkster_registry/composition.py +152 -0
  121. dinkster_registry/grants.py +206 -0
  122. dinkster_registry/install.py +1017 -0
  123. dinkster_registry/model.py +414 -0
  124. dinkster_registry/principals.py +494 -0
  125. dinkster_registry/py.typed +0 -0
  126. dinkster_schema/__init__.py +347 -0
  127. dinkster_schema/capture.py +240 -0
  128. dinkster_schema/coerce.py +186 -0
  129. dinkster_schema/comfy_alias.py +496 -0
  130. dinkster_schema/comfy_group.py +768 -0
  131. dinkster_schema/elaborate.py +676 -0
  132. dinkster_schema/execution.py +24 -0
  133. dinkster_schema/expansion.py +123 -0
  134. dinkster_schema/log.py +206 -0
  135. dinkster_schema/media.py +77 -0
  136. dinkster_schema/model.py +2920 -0
  137. dinkster_schema/names.py +25 -0
  138. dinkster_schema/node.py +137 -0
  139. dinkster_schema/output_descriptors.py +63 -0
  140. dinkster_schema/py.typed +0 -0
  141. dinkster_schema/replace.py +1853 -0
  142. dinkster_schema/reporting.py +441 -0
  143. dinkster_schema/solve.py +178 -0
  144. dinkster_schema/wire.py +1876 -0
  145. dinkster_values/__init__.py +625 -0
  146. dinkster_values/_media_array.py +7 -0
  147. dinkster_values/absent.py +77 -0
  148. dinkster_values/asset_folders.py +64 -0
  149. dinkster_values/assets.py +106 -0
  150. dinkster_values/audio_codec.py +594 -0
  151. dinkster_values/audio_lazy.py +871 -0
  152. dinkster_values/builtin_types.py +181 -0
  153. dinkster_values/curve.py +260 -0
  154. dinkster_values/detection_codec.py +286 -0
  155. dinkster_values/image_codec.py +691 -0
  156. dinkster_values/image_components.py +219 -0
  157. dinkster_values/latent_codec.py +514 -0
  158. dinkster_values/limits.py +52 -0
  159. dinkster_values/lists.py +216 -0
  160. dinkster_values/media_containers.py +70 -0
  161. dinkster_values/model.py +417 -0
  162. dinkster_values/model3d_codec.py +167 -0
  163. dinkster_values/names.py +168 -0
  164. dinkster_values/pins.py +77 -0
  165. dinkster_values/py.typed +0 -0
  166. dinkster_values/registry.py +1105 -0
  167. dinkster_values/resident.py +210 -0
  168. dinkster_values/resources.py +210 -0
  169. dinkster_values/splat_codec.py +477 -0
  170. dinkster_values/storage.py +133 -0
  171. dinkster_values/streams.py +241 -0
  172. dinkster_values/svg_codec.py +120 -0
  173. dinkster_values/timeline_video.py +68 -0
  174. dinkster_values/tuples.py +61 -0
  175. dinkster_values/video_codec.py +897 -0
  176. dinkster_values/video_document.py +315 -0
  177. dinkster_values/video_edits.py +253 -0
  178. dinkster_values/video_probe.py +221 -0
  179. dinkster_video/__init__.py +58 -0
  180. dinkster_video/document.py +352 -0
  181. dinkster_video/formats.py +722 -0
  182. dinkster_video/image_math.py +175 -0
  183. dinkster_video/preview/dinkster-pack.toml +36 -0
  184. dinkster_video/preview/src/dinkster_video_preview/__init__.py +84 -0
  185. dinkster_video/preview/src/dinkster_video_preview/preview.js +45 -0
  186. dinkster_video/py.typed +1 -0
  187. dinkster_video/runtime.py +1561 -0
  188. dinkster_video/timeline.py +576 -0
  189. dinkster_video/timeline_runtime.py +305 -0
  190. dinkster_video_preview/__init__.py +84 -0
  191. dinkster_video_preview/preview.js +45 -0
  192. dinkster_workers/__init__.py +207 -0
  193. dinkster_workers/_doctor_probe.py +359 -0
  194. dinkster_workers/accelerator.py +156 -0
  195. dinkster_workers/aimdo_bootstrap.py +81 -0
  196. dinkster_workers/backend_env.py +1485 -0
  197. dinkster_workers/blobs.py +402 -0
  198. dinkster_workers/boundary.py +1918 -0
  199. dinkster_workers/catalog.py +182 -0
  200. dinkster_workers/devices.py +164 -0
  201. dinkster_workers/diagnostics.py +64 -0
  202. dinkster_workers/dispatch.py +298 -0
  203. dinkster_workers/doctor.py +1382 -0
  204. dinkster_workers/egress.py +344 -0
  205. dinkster_workers/error_hints.py +175 -0
  206. dinkster_workers/execution.py +160 -0
  207. dinkster_workers/governed.py +123 -0
  208. dinkster_workers/headroom.py +156 -0
  209. dinkster_workers/host.py +3116 -0
  210. dinkster_workers/in_process.py +1325 -0
  211. dinkster_workers/interpreter.py +84 -0
  212. dinkster_workers/isolated.py +862 -0
  213. dinkster_workers/launch.py +72 -0
  214. dinkster_workers/manifest.py +3332 -0
  215. dinkster_workers/media.py +196 -0
  216. dinkster_workers/pack_environment.py +473 -0
  217. dinkster_workers/pack_lock.py +359 -0
  218. dinkster_workers/placement.py +215 -0
  219. dinkster_workers/preview_artifacts.py +233 -0
  220. dinkster_workers/produced_assets.py +218 -0
  221. dinkster_workers/provision.py +597 -0
  222. dinkster_workers/py.typed +0 -0
  223. dinkster_workers/relay.py +762 -0
  224. dinkster_workers/remote.py +921 -0
  225. dinkster_workers/resume.py +490 -0
  226. dinkster_workers/routing.py +134 -0
  227. dinkster_workers/run_control.py +275 -0
  228. dinkster_workers/sandbox.py +798 -0
  229. dinkster_workers/saved_artifacts.py +275 -0
  230. dinkster_workers/service.py +593 -0
  231. dinkster_workers/session.py +2605 -0
  232. dinkster_workers/single_job_multi_gpu.py +7 -0
  233. dinkster_workers/staging.py +230 -0
  234. dinkster_workers/transport.py +161 -0
  235. dinkster_workers/workgroup.py +729 -0
  236. dinkster_workers/workgroup_compose.py +135 -0
  237. dinkster_workers/workgroup_config.py +196 -0
  238. dinkster_workers/workgroup_session.py +340 -0
@@ -0,0 +1,344 @@
1
+ """Sigma spaces: how a model family's noise levels map to timesteps.
2
+
3
+ The typed port of ComfyUI's model_sampling *schedule* classes
4
+ (comfy/model_sampling.py ModelSamplingDiscrete / DiscreteFlow / Flux /
5
+ ContinuousEDM @ b78cec87) - the half of model_sampling that answers
6
+ "what sigma is timestep t?" and "what timestep is sigma s?". The
7
+ executing backend owns the *prediction* half (what the model output
8
+ means); ComfyUI fuses both by dynamic multiple inheritance, which the
9
+ plan explicitly rejects.
10
+
11
+ Everything here is pure float math - no torch, no tensors. Values are
12
+ float64 where the reference stores float32 tables; conformance tests
13
+ pin agreement against reference goldens within float32 tolerance.
14
+
15
+ ``percent_to_sigma`` generalizes the reference's hardcoded ``* 999.0``
16
+ to ``* (len(table) - 1)``; identical for the universal 1000-entry case.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import math
22
+ from dataclasses import dataclass, field
23
+ from typing import Protocol
24
+
25
+ #: percent_to_sigma(0.0) for non-flow spaces - the reference's "before
26
+ #: everything" sentinel (comfy/model_sampling.py @ b78cec87).
27
+ SIGMA_PERCENT_ZERO = 999999999.9
28
+
29
+
30
+ def time_snr_shift(alpha: float, t: float) -> float:
31
+ """SD3-style flow shift (comfy/model_sampling.py time_snr_shift
32
+ @ b78cec87)."""
33
+ if alpha == 1.0:
34
+ return t
35
+ return alpha * t / (1 + (alpha - 1) * t)
36
+
37
+
38
+ def flux_time_shift(mu: float, sigma: float, t: float) -> float:
39
+ """Flux exponential flow shift (comfy/model_sampling.py
40
+ flux_time_shift @ b78cec87). ``t`` must be nonzero."""
41
+ return math.exp(mu) / (math.exp(mu) + (1 / t - 1) ** sigma)
42
+
43
+
44
+ class SigmaSpace(Protocol):
45
+ """What schedules and solvers may ask about a model's sigma line.
46
+
47
+ Replaces stage 1's placeholder ScheduleContext: schedules need the
48
+ sigma<->timestep conversions, not just the endpoints. ``table`` is
49
+ the ascending discrete sigma table when the space has one (index 0
50
+ = sigma_min, matching ModelSamplingDiscrete.sigmas @ b78cec87);
51
+ None for spaces that are purely functional.
52
+ """
53
+
54
+ @property
55
+ def sigma_min(self) -> float: ...
56
+
57
+ @property
58
+ def sigma_max(self) -> float: ...
59
+
60
+ @property
61
+ def table(self) -> tuple[float, ...] | None: ...
62
+
63
+ def sigma(self, timestep: float) -> float:
64
+ """The sigma at (possibly fractional) ``timestep``."""
65
+ ...
66
+
67
+ def timestep(self, sigma: float) -> float:
68
+ """The reference model's timestep transform of ``sigma``.
69
+
70
+ NOT necessarily the inverse of ``sigma()``: shifted flow
71
+ spaces (FlowSigmas with shift != 1, FluxFlowSigmas) return
72
+ the unshifted ``sigma * 1000`` exactly as the reference
73
+ (ModelSamplingDiscreteFlow.timestep @ b78cec87) - fidelity
74
+ to that mapping is the contract, invertibility is not."""
75
+ ...
76
+
77
+ def percent_to_sigma(self, percent: float) -> float:
78
+ """Sigma bound for a "first/last N% of sampling" range."""
79
+ ...
80
+
81
+
82
+ def linear_beta_sigmas(
83
+ *,
84
+ linear_start: float = 0.00085,
85
+ linear_end: float = 0.012,
86
+ timesteps: int = 1000,
87
+ zsnr: bool = False,
88
+ ) -> tuple[float, ...]:
89
+ """The discrete sigma table of a linear-beta DDPM schedule.
90
+
91
+ Ports make_beta_schedule("linear") + ModelSamplingDiscrete
92
+ _register_schedule (comfy/ldm/modules/diffusionmodules/util.py,
93
+ comfy/model_sampling.py @ b78cec87): betas are squared linspace in
94
+ sqrt-space, sigmas are sqrt((1 - cumprod(alpha)) / cumprod(alpha)).
95
+ Defaults are the SD15/SDXL settings.
96
+ """
97
+ if timesteps < 1:
98
+ raise ValueError("timesteps must be >= 1")
99
+ start = math.sqrt(linear_start)
100
+ end = math.sqrt(linear_end)
101
+ alphas_cumprod: list[float] = []
102
+ running = 1.0
103
+ for i in range(timesteps):
104
+ frac = i / (timesteps - 1) if timesteps > 1 else 0.0
105
+ beta = (start + (end - start) * frac) ** 2
106
+ running *= 1.0 - beta
107
+ alphas_cumprod.append(running)
108
+ sigmas = tuple(math.sqrt((1.0 - ac) / ac) for ac in alphas_cumprod)
109
+ if zsnr:
110
+ sigmas = _rescale_zero_terminal_snr_sigmas(sigmas)
111
+ return sigmas
112
+
113
+
114
+ def _rescale_zero_terminal_snr_sigmas(
115
+ sigmas: tuple[float, ...],
116
+ ) -> tuple[float, ...]:
117
+ """Zero-terminal-SNR rescale (comfy/model_sampling.py
118
+ rescale_zero_terminal_snr_sigmas @ b78cec87)."""
119
+ alphas_bar_sqrt = [math.sqrt(1.0 / (s * s + 1.0)) for s in sigmas]
120
+ first = alphas_bar_sqrt[0]
121
+ last = alphas_bar_sqrt[-1]
122
+ scale = first / (first - last)
123
+ alphas_bar = [((a - last) * scale) ** 2 for a in alphas_bar_sqrt]
124
+ alphas_bar[-1] = 4.8973451890853435e-08
125
+ return tuple(math.sqrt((1.0 - ab) / ab) for ab in alphas_bar)
126
+
127
+
128
+ @dataclass(frozen=True)
129
+ class DiscreteSigmas:
130
+ """A table-backed sigma space (ModelSamplingDiscrete @ b78cec87).
131
+
132
+ ``sigma()`` interpolates linearly in log-sigma between adjacent
133
+ table entries; ``timestep()`` returns the index whose log-sigma is
134
+ nearest (both exactly as the reference).
135
+ """
136
+
137
+ entries: tuple[float, ...]
138
+ _log: tuple[float, ...] = field(init=False, repr=False)
139
+
140
+ def __post_init__(self) -> None:
141
+ if len(self.entries) < 2:
142
+ raise ValueError("a discrete sigma table needs at least 2 entries")
143
+ if any(s <= 0 for s in self.entries):
144
+ raise ValueError("sigma table entries must be positive")
145
+ if any(a >= b for a, b in zip(self.entries, self.entries[1:], strict=False)):
146
+ raise ValueError("sigma table must be strictly ascending")
147
+ object.__setattr__(self, "_log", tuple(math.log(s) for s in self.entries))
148
+
149
+ @classmethod
150
+ def linear_beta(
151
+ cls,
152
+ *,
153
+ linear_start: float = 0.00085,
154
+ linear_end: float = 0.012,
155
+ timesteps: int = 1000,
156
+ zsnr: bool = False,
157
+ ) -> DiscreteSigmas:
158
+ return cls(
159
+ linear_beta_sigmas(
160
+ linear_start=linear_start,
161
+ linear_end=linear_end,
162
+ timesteps=timesteps,
163
+ zsnr=zsnr,
164
+ )
165
+ )
166
+
167
+ @property
168
+ def sigma_min(self) -> float:
169
+ return self.entries[0]
170
+
171
+ @property
172
+ def sigma_max(self) -> float:
173
+ return self.entries[-1]
174
+
175
+ @property
176
+ def table(self) -> tuple[float, ...] | None:
177
+ return self.entries
178
+
179
+ def sigma(self, timestep: float) -> float:
180
+ t = min(max(timestep, 0.0), len(self.entries) - 1)
181
+ low = math.floor(t)
182
+ high = math.ceil(t)
183
+ w = t - low
184
+ return math.exp((1.0 - w) * self._log[low] + w * self._log[high])
185
+
186
+ def timestep(self, sigma: float) -> float:
187
+ log_sigma = math.log(sigma)
188
+ return float(
189
+ min(
190
+ range(len(self._log)),
191
+ key=lambda i: abs(log_sigma - self._log[i]),
192
+ )
193
+ )
194
+
195
+ def percent_to_sigma(self, percent: float) -> float:
196
+ if percent <= 0.0:
197
+ return SIGMA_PERCENT_ZERO
198
+ if percent >= 1.0:
199
+ return 0.0
200
+ return self.sigma((1.0 - percent) * (len(self.entries) - 1))
201
+
202
+
203
+ @dataclass(frozen=True)
204
+ class FlowSigmas:
205
+ """SD3-style discrete flow space (ModelSamplingDiscreteFlow
206
+ @ b78cec87): sigma(t) = time_snr_shift(shift, t / multiplier)."""
207
+
208
+ shift: float = 1.0
209
+ multiplier: float = 1000.0
210
+ timesteps: int = 1000
211
+
212
+ def __post_init__(self) -> None:
213
+ if self.timesteps < 1:
214
+ raise ValueError("timesteps must be >= 1")
215
+ if self.multiplier <= 0:
216
+ raise ValueError("multiplier must be positive")
217
+
218
+ @property
219
+ def sigma_min(self) -> float:
220
+ return self.sigma(self.multiplier / self.timesteps)
221
+
222
+ @property
223
+ def sigma_max(self) -> float:
224
+ return self.sigma(self.multiplier)
225
+
226
+ @property
227
+ def table(self) -> tuple[float, ...] | None:
228
+ return tuple(
229
+ self.sigma((i / self.timesteps) * self.multiplier) for i in range(1, self.timesteps + 1)
230
+ )
231
+
232
+ def sigma(self, timestep: float) -> float:
233
+ return time_snr_shift(self.shift, timestep / self.multiplier)
234
+
235
+ def timestep(self, sigma: float) -> float:
236
+ return sigma * self.multiplier
237
+
238
+ def percent_to_sigma(self, percent: float) -> float:
239
+ if percent <= 0.0:
240
+ return 1.0
241
+ if percent >= 1.0:
242
+ return 0.0
243
+ return time_snr_shift(self.shift, 1.0 - percent)
244
+
245
+
246
+ @dataclass(frozen=True)
247
+ class FluxFlowSigmas:
248
+ """Flux exponential flow space (ModelSamplingFlux @ b78cec87):
249
+ sigma(t) = flux_time_shift(shift, 1.0, t), t in (0, 1]."""
250
+
251
+ shift: float = 1.15
252
+ timesteps: int = 10000
253
+
254
+ def __post_init__(self) -> None:
255
+ if self.timesteps < 1:
256
+ raise ValueError("timesteps must be >= 1")
257
+
258
+ @property
259
+ def sigma_min(self) -> float:
260
+ return self.sigma(1.0 / self.timesteps)
261
+
262
+ @property
263
+ def sigma_max(self) -> float:
264
+ return self.sigma(1.0)
265
+
266
+ @property
267
+ def table(self) -> tuple[float, ...] | None:
268
+ return tuple(self.sigma(i / self.timesteps) for i in range(1, self.timesteps + 1))
269
+
270
+ def sigma(self, timestep: float) -> float:
271
+ return flux_time_shift(self.shift, 1.0, timestep)
272
+
273
+ def timestep(self, sigma: float) -> float:
274
+ return sigma
275
+
276
+ def percent_to_sigma(self, percent: float) -> float:
277
+ if percent <= 0.0:
278
+ return 1.0
279
+ if percent >= 1.0:
280
+ return 0.0
281
+ return flux_time_shift(self.shift, 1.0, 1.0 - percent)
282
+
283
+
284
+ @dataclass(frozen=True)
285
+ class ContinuousEDMSigmas:
286
+ """Continuous EDM space (ModelSamplingContinuousEDM @ b78cec87):
287
+ timestep = 0.25 * ln(sigma). The reference materializes a
288
+ 1000-entry log-spaced table "for compatibility with some
289
+ schedulers"; so does this."""
290
+
291
+ min_sigma: float = 0.002
292
+ max_sigma: float = 120.0
293
+ timesteps: int = 1000
294
+
295
+ def __post_init__(self) -> None:
296
+ if not math.isfinite(self.min_sigma) or not math.isfinite(self.max_sigma):
297
+ raise ValueError("sigma bounds must be finite")
298
+ if self.min_sigma <= 0 or self.max_sigma <= self.min_sigma:
299
+ raise ValueError("need 0 < min_sigma < max_sigma")
300
+ if self.timesteps < 2:
301
+ raise ValueError("timesteps must be >= 2")
302
+
303
+ @property
304
+ def sigma_min(self) -> float:
305
+ return self.min_sigma
306
+
307
+ @property
308
+ def sigma_max(self) -> float:
309
+ return self.max_sigma
310
+
311
+ @property
312
+ def table(self) -> tuple[float, ...] | None:
313
+ lo = math.log(self.min_sigma)
314
+ hi = math.log(self.max_sigma)
315
+ n = self.timesteps
316
+ return tuple(math.exp(lo + (hi - lo) * i / (n - 1)) for i in range(n))
317
+
318
+ def sigma(self, timestep: float) -> float:
319
+ return math.exp(timestep / 0.25)
320
+
321
+ def timestep(self, sigma: float) -> float:
322
+ return 0.25 * math.log(sigma)
323
+
324
+ def percent_to_sigma(self, percent: float) -> float:
325
+ if percent <= 0.0:
326
+ return SIGMA_PERCENT_ZERO
327
+ if percent >= 1.0:
328
+ return 0.0
329
+ lo = math.log(self.min_sigma)
330
+ hi = math.log(self.max_sigma)
331
+ return math.exp((hi - lo) * (1.0 - percent) + lo)
332
+
333
+
334
+ __all__ = [
335
+ "ContinuousEDMSigmas",
336
+ "DiscreteSigmas",
337
+ "FlowSigmas",
338
+ "FluxFlowSigmas",
339
+ "SIGMA_PERCENT_ZERO",
340
+ "SigmaSpace",
341
+ "flux_time_shift",
342
+ "linear_beta_sigmas",
343
+ "time_snr_shift",
344
+ ]