LatentOperationNormalizeMinMax
Squash your latent into 0–1 and hope nothing is an outlier
- op
LatentOperationNormalizeMinMax does exactly what its name says: (x − min) / (max − min), mapped across the whole latent so the smallest value becomes 0 and the largest becomes 1. Everything in between gets stretched to fit. It's the node you want when something downstream expects a 0–1 range and you don't care about the distribution's shape - and it's the node you'll regret reaching for the moment your latent has one stubborn outlier.
The mechanism
min_val = latent.min()
max_val = latent.max()
return (latent - min_val) / (max_val - min_val + eps)
eps = 1e-8 keeps a flat latent from dividing by zero. There are no inputs at all - no axis, no clamp, no target range. The node takes a latent, does a global min/max stretch, done. The float32 wrapper applies as it does for every normalize node in this pack, so fp16 latents get the variance math done safely and cast back without spitting NaNs (the fp16-overflow-on-stats failure mode the KB's troubleshooting doc warns about).
The catch is the phrase "global min/max." Min-max normalization is entirely hostage to the single most extreme value. Latents are noisy clouds, and a lone extreme spike - a hot pixel channel, a stray value from an earlier op - will set your 0 and 1, and then crush everything else into a thin band in the middle. If your latent has a wild outlier, this node produces a washed-out, low-contrast result and you'll blame the wrong thing. That's precisely why the pack also ships LatentOperationNormalizePercentile, which uses the 1st/99th percentile instead of the true min/max and shrugs at outliers.
The family context
Within hnmr293/ComfyUI-latent-ops, this is the "give me a clean 0–1 latent" node - the natural prelude to the pack's own Latent01ToImage (which turns a 0–1 latent into an IMAGE tensor for previewing), and a decent way to get a latent into a range that a custom consumer expects. It does not give you zero mean or unit variance - that's LatentOperationNormalize. Different tools: min-max is about range, z-score is about distribution shape. If you just want a previewable image, min-max onto 0–1 plus Latent01ToImage is the honest path; if you want statistical normalization for feeding another algorithm, use the z-score family instead.
The op output
No inputs, one output: op, type LATENT_OPERATION - a deferred closure, not a result. This pack builds operations and ships no apply node, so you need a consumer of LATENT_OPERATION (Sonar's SonarApplyLatentOperationCFG exists in the wild) or your own apply node. Wire op straight into a VAE Decode and ComfyUI throws a type mismatch - the pack's universal first-encounter trap, and it's by design, not a bug in your graph.
Install
Same story as every node here. ComfyUI Manager → search ComfyUI-latent-ops, or:
cd ComfyUI/custom_nodes
git clone https://github.com/hnmr293/ComfyUI-latent-ops
Restart. No requirements.txt, no downloads, pure PyTorch. This is hnmr293's private latent workbench (he's the sd-webui-cutoff / llul author), and the pack is essentially unmarketed - the source in latent_ops/normalize.py is your real documentation. Everything registers under hnmr/latent_ops.
Inputs (0)
No inputs
Outputs (1)
| Name | Type | Description |
|---|---|---|
| op | LATENT_OPERATION | — |