lsnu commited on
Commit
13cfc22
·
verified ·
1 Parent(s): 7b8de56

Add all-metrics-only GIF render mode

Browse files
code/scripts/render_oven_metric_gifs.py CHANGED
@@ -17,6 +17,33 @@ if str(PROJECT_ROOT) not in sys.path:
17
  sys.path.insert(0, str(PROJECT_ROOT))
18
 
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  def _launch_xvfb(display_num: int, log_path: Path) -> subprocess.Popen:
21
  log_handle = log_path.open("w", encoding="utf-8")
22
  return subprocess.Popen(
@@ -146,6 +173,7 @@ def main() -> int:
146
  parser.add_argument("--checkpoint-stride", type=int, default=16)
147
  parser.add_argument("--num-workers", type=int, default=6)
148
  parser.add_argument("--base-display", type=int, default=190)
 
149
  args = parser.parse_args()
150
 
151
  episode_dir = Path(args.episode_dir)
@@ -182,18 +210,29 @@ def main() -> int:
182
  visibility_dir = frames_dir.joinpath("visibility_focus")
183
  path_dir = frames_dir.joinpath("path_quality_focus")
184
  all_dir = frames_dir.joinpath("all_metrics")
185
- for directory in [visibility_dir, path_dir, all_dir]:
186
- directory.mkdir(parents=True, exist_ok=True)
 
 
 
187
 
188
- visibility_frames = _range_inclusive(max(0, phase_cross - 12), min(max_frame, phase_cross + 28), 1)
189
- path_start = max(0, min(phase_cross, pext_cross) - 16)
190
- path_end = min(max_frame, max(pext_cross, ready_cross, retrieve_cross) + 24)
191
- path_frames = sorted(
192
- set(
193
- _range_inclusive(path_start, min(path_end, max(path_start, pext_cross - 18)), 2)
194
- + _range_inclusive(max(path_start, pext_cross - 18), path_end, 1)
 
 
 
 
 
 
 
 
 
195
  )
196
- )
197
  all_frames = _range_inclusive(0, max_frame, 2)
198
  unique_frames = sorted(set(visibility_frames) | set(path_frames) | set(all_frames))
199
 
@@ -250,47 +289,58 @@ def main() -> int:
250
  visibility_pngs = [visibility_dir.joinpath(f"frame_{frame:04d}.png") for frame in visibility_frames]
251
  path_pngs = [path_dir.joinpath(f"frame_{frame:04d}.png") for frame in path_frames]
252
  all_pngs = [all_dir.joinpath(f"frame_{frame:04d}.png") for frame in all_frames]
253
- for path in visibility_pngs + path_pngs + all_pngs:
254
  if not path.exists():
255
  raise RuntimeError(f"missing rendered frame: {path}")
256
 
257
- _assemble_gif(
258
- visibility_pngs,
259
- output_dir.joinpath(f"{episode_name}_visibility_focus.gif"),
260
- duration_ms=120,
261
- )
262
- _assemble_gif(
263
- path_pngs,
264
- output_dir.joinpath(f"{episode_name}_path_quality_focus.gif"),
265
- duration_ms=160,
266
- )
 
267
  _assemble_gif(
268
  all_pngs,
269
  output_dir.joinpath(f"{episode_name}_all_metrics.gif"),
270
  duration_ms=100,
271
  )
272
 
273
- readme = output_dir.joinpath("README.md")
274
- readme.write_text(
275
- "\n".join(
 
 
 
 
 
276
  [
277
- "# Visualizations",
278
- "",
279
  f"- `{episode_name}_visibility_focus.gif`: three-view visibility montage over dense frames {visibility_frames[0]}-{visibility_frames[-1]}.",
280
  f"- `{episode_name}_path_quality_focus.gif`: debug-aware p_ext planner montage over dense frames {path_frames[0]}-{path_frames[-1]}.",
281
- f"- `{episode_name}_all_metrics.gif`: full episode overlay GIF over dense frames 0-{max_frame}, sampled every 2 frames.",
282
  "- `frames/visibility_focus/`: per-frame PNGs with scene overlays, x-ray projections, and tray-mask views.",
283
  "- `frames/path_quality_focus/`: per-frame PNGs with demo wrist trails, milestone pose overlays, and p_ext planner-search tables from the debug JSONL sidecar.",
284
- "- `frames/all_metrics/`: per-frame PNGs with the episode-wide metric bars and phase banner.",
285
- "",
286
- "Legend highlights:",
 
 
 
 
 
 
 
 
 
287
  "- Visibility: blue = sampled tray surface, magenta = sampled grasp region, green = depth-consistent visible grasp samples.",
288
  "- Path quality: cyan/purple = recent left/right demo wrist trails, yellow = pregrasp, orange = grasp, green = retreat / extraction path.",
289
- "- All metrics: red banner = reveal phase, green banner = retrieve phase.",
290
  ]
291
- ),
292
- encoding="utf-8",
293
- )
294
  print(output_dir)
295
  return 0
296
 
 
17
  sys.path.insert(0, str(PROJECT_ROOT))
18
 
19
 
20
+ def _configure_thread_env() -> None:
21
+ defaults = {
22
+ "OMP_NUM_THREADS": "1",
23
+ "OPENBLAS_NUM_THREADS": "1",
24
+ "MKL_NUM_THREADS": "1",
25
+ "NUMEXPR_NUM_THREADS": "1",
26
+ "VECLIB_MAXIMUM_THREADS": "1",
27
+ "BLIS_NUM_THREADS": "1",
28
+ }
29
+ for key, value in defaults.items():
30
+ os.environ.setdefault(key, value)
31
+
32
+
33
+ def _configure_coppeliasim_env() -> None:
34
+ coppeliasim_root = os.environ.setdefault("COPPELIASIM_ROOT", "/workspace/coppelia_sim")
35
+ ld_library_path_parts = [
36
+ part for part in os.environ.get("LD_LIBRARY_PATH", "").split(":") if part
37
+ ]
38
+ if coppeliasim_root not in ld_library_path_parts:
39
+ ld_library_path_parts.insert(0, coppeliasim_root)
40
+ os.environ["LD_LIBRARY_PATH"] = ":".join(ld_library_path_parts)
41
+
42
+
43
+ _configure_thread_env()
44
+ _configure_coppeliasim_env()
45
+
46
+
47
  def _launch_xvfb(display_num: int, log_path: Path) -> subprocess.Popen:
48
  log_handle = log_path.open("w", encoding="utf-8")
49
  return subprocess.Popen(
 
173
  parser.add_argument("--checkpoint-stride", type=int, default=16)
174
  parser.add_argument("--num-workers", type=int, default=6)
175
  parser.add_argument("--base-display", type=int, default=190)
176
+ parser.add_argument("--all-metrics-only", action="store_true")
177
  args = parser.parse_args()
178
 
179
  episode_dir = Path(args.episode_dir)
 
210
  visibility_dir = frames_dir.joinpath("visibility_focus")
211
  path_dir = frames_dir.joinpath("path_quality_focus")
212
  all_dir = frames_dir.joinpath("all_metrics")
213
+ if args.all_metrics_only:
214
+ all_dir.mkdir(parents=True, exist_ok=True)
215
+ else:
216
+ for directory in [visibility_dir, path_dir, all_dir]:
217
+ directory.mkdir(parents=True, exist_ok=True)
218
 
219
+ if args.all_metrics_only:
220
+ visibility_frames = []
221
+ path_frames = []
222
+ else:
223
+ visibility_frames = _range_inclusive(
224
+ max(0, phase_cross - 12), min(max_frame, phase_cross + 28), 1
225
+ )
226
+ path_start = max(0, min(phase_cross, pext_cross) - 16)
227
+ path_end = min(max_frame, max(pext_cross, ready_cross, retrieve_cross) + 24)
228
+ path_frames = sorted(
229
+ set(
230
+ _range_inclusive(
231
+ path_start, min(path_end, max(path_start, pext_cross - 18)), 2
232
+ )
233
+ + _range_inclusive(max(path_start, pext_cross - 18), path_end, 1)
234
+ )
235
  )
 
236
  all_frames = _range_inclusive(0, max_frame, 2)
237
  unique_frames = sorted(set(visibility_frames) | set(path_frames) | set(all_frames))
238
 
 
289
  visibility_pngs = [visibility_dir.joinpath(f"frame_{frame:04d}.png") for frame in visibility_frames]
290
  path_pngs = [path_dir.joinpath(f"frame_{frame:04d}.png") for frame in path_frames]
291
  all_pngs = [all_dir.joinpath(f"frame_{frame:04d}.png") for frame in all_frames]
292
+ for path in all_pngs + visibility_pngs + path_pngs:
293
  if not path.exists():
294
  raise RuntimeError(f"missing rendered frame: {path}")
295
 
296
+ if not args.all_metrics_only:
297
+ _assemble_gif(
298
+ visibility_pngs,
299
+ output_dir.joinpath(f"{episode_name}_visibility_focus.gif"),
300
+ duration_ms=120,
301
+ )
302
+ _assemble_gif(
303
+ path_pngs,
304
+ output_dir.joinpath(f"{episode_name}_path_quality_focus.gif"),
305
+ duration_ms=160,
306
+ )
307
  _assemble_gif(
308
  all_pngs,
309
  output_dir.joinpath(f"{episode_name}_all_metrics.gif"),
310
  duration_ms=100,
311
  )
312
 
313
+ readme_lines = [
314
+ "# Visualizations",
315
+ "",
316
+ f"- `{episode_name}_all_metrics.gif`: full episode overlay GIF over dense frames 0-{max_frame}, sampled every 2 frames.",
317
+ "- `frames/all_metrics/`: per-frame PNGs with the episode-wide metric bars and phase banner.",
318
+ ]
319
+ if not args.all_metrics_only:
320
+ readme_lines.extend(
321
  [
 
 
322
  f"- `{episode_name}_visibility_focus.gif`: three-view visibility montage over dense frames {visibility_frames[0]}-{visibility_frames[-1]}.",
323
  f"- `{episode_name}_path_quality_focus.gif`: debug-aware p_ext planner montage over dense frames {path_frames[0]}-{path_frames[-1]}.",
 
324
  "- `frames/visibility_focus/`: per-frame PNGs with scene overlays, x-ray projections, and tray-mask views.",
325
  "- `frames/path_quality_focus/`: per-frame PNGs with demo wrist trails, milestone pose overlays, and p_ext planner-search tables from the debug JSONL sidecar.",
326
+ ]
327
+ )
328
+ readme_lines.extend(
329
+ [
330
+ "",
331
+ "Legend highlights:",
332
+ "- All metrics: red banner = reveal phase, green banner = retrieve phase.",
333
+ ]
334
+ )
335
+ if not args.all_metrics_only:
336
+ readme_lines.extend(
337
+ [
338
  "- Visibility: blue = sampled tray surface, magenta = sampled grasp region, green = depth-consistent visible grasp samples.",
339
  "- Path quality: cyan/purple = recent left/right demo wrist trails, yellow = pregrasp, orange = grasp, green = retreat / extraction path.",
 
340
  ]
341
+ )
342
+ readme = output_dir.joinpath("README.md")
343
+ readme.write_text("\n".join(readme_lines), encoding="utf-8")
344
  print(output_dir)
345
  return 0
346