STATICAI commited on
Commit
8f65673
Β·
verified Β·
1 Parent(s): 12a52cb

Restore patch_runtime.py from Make-It-Animatable

Browse files
Files changed (1) hide show
  1. patch_runtime.py +100 -0
patch_runtime.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import os
3
+ import subprocess
4
+
5
+ # The upstream checkout lives on persistent storage and therefore retains edits
6
+ # across container restarts. Restore only the files managed by this patcher from
7
+ # its pinned Git commit before applying changes, making this script idempotent.
8
+ for relative_path in (
9
+ "util/dataset_mixamo_additional.py",
10
+ "model.py",
11
+ "models_ae.py",
12
+ "app.py",
13
+ ):
14
+ pristine = subprocess.check_output(
15
+ ["git", "-C", "app", "show", f"HEAD:{relative_path}"]
16
+ )
17
+ Path("app", relative_path).write_bytes(pristine)
18
+
19
+ # ── 1. dataset_mixamo_additional.py β€” optional extended skeleton guard ─────────
20
+ path = Path("app/util/dataset_mixamo_additional.py")
21
+ if path.exists():
22
+ source = path.read_text()
23
+ old = """TEMPLATE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "../data/Mixamo/bones_vroid.fbx"))
24
+ KINEMATIC_TREE = get_kinematic_tree(TEMPLATE_PATH, BONES_IDX_DICT)
25
+ assert len(KINEMATIC_TREE) == len(MIXAMO_JOINTS)
26
+ """
27
+ new = """TEMPLATE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "../data/Mixamo/bones_vroid.fbx"))
28
+ if os.path.isfile(TEMPLATE_PATH):
29
+ KINEMATIC_TREE = get_kinematic_tree(TEMPLATE_PATH, BONES_IDX_DICT)
30
+ assert len(KINEMATIC_TREE) == len(MIXAMO_JOINTS)
31
+ else:
32
+ # The optional extended skeleton lives in the restricted Mixamo dataset.
33
+ # Standard humanoid inference does not use it (joints_additional=False).
34
+ KINEMATIC_TREE = dataset_mixamo.KINEMATIC_TREE
35
+ """
36
+ if old in source:
37
+ path.write_text(source.replace(old, new))
38
+ print("[dataset_mixamo_additional.py] extended-skeleton guard patched")
39
+ else:
40
+ print("[dataset_mixamo_additional.py] already patched or block not found")
41
+
42
+ # ── fps fallback: replaces torch_cluster.fps with pytorch3d equivalent ─────────
43
+ FPS_FALLBACK = """try:
44
+ from torch_cluster import fps
45
+ except ImportError:
46
+ import numpy as np
47
+ from pytorch3d.ops import sample_farthest_points
48
+
49
+ def fps(x, batch, ratio):
50
+ import torch
51
+ sampled = []
52
+ for batch_id in torch.unique(batch, sorted=True):
53
+ global_idx = torch.nonzero(batch == batch_id, as_tuple=False).flatten()
54
+ points = x[global_idx].unsqueeze(0)
55
+ count = max(1, int(np.ceil(points.shape[1] * ratio)))
56
+ _, local_idx = sample_farthest_points(points, K=count, random_start_point=True)
57
+ sampled.append(global_idx[local_idx[0]])
58
+ return torch.cat(sampled)
59
+ """
60
+ CLUSTER_IMPORT = "from torch_cluster import fps"
61
+
62
+ # ── 2. model.py ───────────────────────────────────────────────────────────────
63
+ model_path = Path("app/model.py")
64
+ if model_path.exists():
65
+ src = model_path.read_text()
66
+ if CLUSTER_IMPORT in src:
67
+ model_path.write_text(src.replace(CLUSTER_IMPORT, FPS_FALLBACK, 1))
68
+ print("[model.py] torch_cluster fps patched")
69
+ else:
70
+ print("[model.py] already patched")
71
+ else:
72
+ print("[model.py] not found")
73
+
74
+ # ── 3. models_ae.py β€” THE CRITICAL MISSING PATCH ─────────────────────────────
75
+ # The original patch_runtime.py only patched model.py but NOT models_ae.py,
76
+ # which also imports torch_cluster. This caused the ModuleNotFoundError.
77
+ models_ae_path = Path("app/models_ae.py")
78
+ if models_ae_path.exists():
79
+ src = models_ae_path.read_text()
80
+ if CLUSTER_IMPORT in src:
81
+ models_ae_path.write_text(src.replace(CLUSTER_IMPORT, FPS_FALLBACK, 1))
82
+ print("[models_ae.py] torch_cluster fps patched")
83
+ else:
84
+ print("[models_ae.py] already patched")
85
+ else:
86
+ print("[models_ae.py] not found")
87
+
88
+ # ── 4. app/app.py β€” @spaces.GPU duration ─────────────────────────────────────
89
+ app_path = Path("app/app.py")
90
+ if app_path.exists():
91
+ src = app_path.read_text()
92
+ bare_gpu_decorators = src.count("@spaces.GPU\n")
93
+ if bare_gpu_decorators != 2:
94
+ raise RuntimeError(f"Expected 2 bare GPU decorators, found {bare_gpu_decorators}")
95
+ app_path.write_text(src.replace("@spaces.GPU\n", "@spaces.GPU(duration=300)\n"))
96
+ print(f"[app/app.py] {bare_gpu_decorators} @spaces.GPU -> duration=300 patched")
97
+ else:
98
+ print("[app/app.py] not found")
99
+
100
+ print("patch_runtime.py done.")