Download ComfyUI-MiniMaxH3-Context-Loop/ComfyUI-MAINodes/tests/test_v2v_time_mask.py from dzmdd/Fast_deploy: direct link, hf CLI and curl.
- Browser
- Download file 4.8 kB
-
https://huggingface.co/dzmdd/Fast_deploy/resolve/main/ComfyUI-MiniMaxH3-Context-Loop/ComfyUI-MAINodes/tests/test_v2v_time_mask.py
- Command line
-
hf download hf://dzmdd/Fast_deploy/ComfyUI-MiniMaxH3-Context-Loop/ComfyUI-MAINodes/tests/test_v2v_time_mask.py
-
curl -L -o test_v2v_time_mask.py https://huggingface.co/dzmdd/Fast_deploy/resolve/main/ComfyUI-MiniMaxH3-Context-Loop/ComfyUI-MAINodes/tests/test_v2v_time_mask.py
4.8 kB
| #!/usr/bin/env python3 | |
| """Unit test for H3 V2V Init's time-varying freeze mask (torch only, no GPU, | |
| no ComfyUI process). | |
| python tests/test_v2v_time_mask.py | |
| Checks the pixel-frame -> latent-token map and the pooling that rides on it: | |
| spans tile the clip exactly for legal lengths, every 5th token is a singleton | |
| sitting on a 17-multiple frame, a mask that switches on AT a 17-multiple | |
| lights that singleton and nothing earlier, a mixed token max-pools (any | |
| regenerate frame wins), off-length masks resample nearest, and a T==1 mask | |
| reproduces the static-union result. | |
| Exit code 0 = pass. | |
| """ | |
| import os | |
| import sys | |
| import torch | |
| HERE = os.path.dirname(os.path.abspath(__file__)) | |
| sys.path.insert(0, os.path.dirname(HERE)) | |
| import importlib.util | |
| spec = importlib.util.spec_from_file_location( | |
| "mainodes_motion", os.path.join(os.path.dirname(HERE), "motion.py")) | |
| motion = importlib.util.module_from_spec(spec) | |
| spec.loader.exec_module(motion) | |
| LEGAL = [39, 90, 141, 192] | |
| def t_lat_of(length): | |
| return (length - 5) // 17 * 5 + 2 | |
| def test_spans(): | |
| for length in LEGAL: | |
| t_lat = t_lat_of(length) | |
| spans = motion._token_frame_spans(t_lat) | |
| # inverts the node's own t_lat -> length formula | |
| assert (t_lat - 2) // 5 * 17 + 5 == length, length | |
| # tile [0, length) with no gap or overlap | |
| assert spans[0][0] == 0 and spans[-1][1] == length - 1, spans[-1] | |
| for (a, b), (c, _) in zip(spans, spans[1:]): | |
| assert b == c - 1, (a, b, c) | |
| sizes = [b - a + 1 for a, b in spans] | |
| assert sum(sizes) == length, (sum(sizes), length) | |
| # (1,4,4,4,4) rhythm; singletons on 17-multiples | |
| for t, (a, b) in enumerate(spans): | |
| if t % 5 == 0: | |
| assert (a, b) == (17 * (t // 5),) * 2, (t, a, b) | |
| else: | |
| assert b - a + 1 == 4, (t, a, b) | |
| print(f"PASS spans len={length}: t_lat={t_lat} sizes={sizes} " | |
| f"singleton frames={[a for t, (a, b) in enumerate(spans) if t % 5 == 0]}") | |
| def test_switch_on_17(): | |
| for length in (39, 141): | |
| t_lat = t_lat_of(length) | |
| for onset in range(17, length, 17): | |
| m = torch.zeros(length, 2, 2) | |
| m[onset:] = 1.0 | |
| tok = motion._tokenize_mask_time(m, t_lat, length) | |
| hot = [t for t in range(t_lat) if tok[t].max() > 0] | |
| first = onset // 17 * 5 | |
| assert hot == list(range(first, t_lat)), (length, onset, hot) | |
| assert first % 5 == 0 | |
| print(f"PASS onset len={length} frame={onset}: first hot token " | |
| f"{first} (singleton), tokens 0..{first - 1} cold") | |
| def test_mixed_token_maxpool(): | |
| length, t_lat = 39, t_lat_of(39) | |
| spans = motion._token_frame_spans(t_lat) | |
| a, b = spans[3] # a 4-frame token | |
| assert (a, b) == (9, 12), spans[3] | |
| for f in range(a, b + 1): | |
| m = torch.zeros(length, 1, 1) | |
| m[f] = 1.0 | |
| tok = motion._tokenize_mask_time(m, t_lat, length) | |
| hot = [t for t in range(t_lat) if tok[t].max() > 0] | |
| assert hot == [3], (f, hot) | |
| # partial spatial coverage: the union of the covered frames' pixels | |
| m = torch.zeros(length, 1, 4) | |
| m[9, 0, 0] = 1.0 | |
| m[12, 0, 3] = 1.0 | |
| tok = motion._tokenize_mask_time(m, t_lat, length) | |
| assert tok[3].flatten().tolist() == [1.0, 0.0, 0.0, 1.0], tok[3] | |
| print("PASS mixed token: frames 9..12 all light token 3 only; " | |
| "pixel-wise max within the token = [1,0,0,1]") | |
| def test_resample(): | |
| length, t_lat = 90, t_lat_of(90) | |
| # half-rate mask: frame f of the clip reads source frame floor(f/2) | |
| src = torch.zeros(45, 1, 1) | |
| src[9:] = 1.0 # -> clip frames 18.. are hot | |
| tok = motion._tokenize_mask_time(src, t_lat, length) | |
| hot = [t for t in range(t_lat) if tok[t].max() > 0] | |
| # frame 18 sits in token 5*1+1 = 6 (span 18..21) | |
| assert hot == list(range(6, t_lat)), hot | |
| ref = torch.zeros(length, 1, 1) | |
| ref[18:] = 1.0 | |
| assert torch.equal(tok, motion._tokenize_mask_time(ref, t_lat, length)) | |
| print(f"PASS resample: T=45 -> {length} nearest, onset frame 18 -> first " | |
| f"hot token 6, identical to the already-length mask") | |
| def test_t1_equals_static(): | |
| for length in LEGAL: | |
| t_lat = t_lat_of(length) | |
| m = (torch.rand(1, 6, 7) > 0.5).float() | |
| tok = motion._tokenize_mask_time(m, t_lat, length) | |
| static = m.max(dim=0, keepdim=True).values.expand(t_lat, 6, 7) | |
| assert torch.equal(tok, static), length | |
| print("PASS T==1: pooled result equals the static-union expand for " | |
| f"lengths {LEGAL}") | |
| if __name__ == "__main__": | |
| test_spans() | |
| test_switch_on_17() | |
| test_mixed_token_maxpool() | |
| test_resample() | |
| test_t1_equals_static() | |
| print("ALL PASS") | |