euler-train 2.4.1__tar.gz → 2.5.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: euler-train
3
- Version: 2.4.1
3
+ Version: 2.5.0
4
4
  Summary: Lightweight file-based experiment logger for PyTorch
5
5
  Requires-Python: >=3.9
6
6
  Requires-Dist: numpy
@@ -68,10 +68,19 @@ def _save_slot(
68
68
  visualization_overrides: dict[str, Any],
69
69
  ) -> None:
70
70
  slot_dir.mkdir(parents=True, exist_ok=True)
71
- items = _unpack(data)
72
71
  visualization = _resolve_visualization(
73
72
  output_type, leaf_name, visualization_overrides,
74
73
  )
74
+
75
+ # Dict with string keys → named outputs (e.g. {"scene_042": img}).
76
+ if isinstance(data, dict):
77
+ for name, raw in data.items():
78
+ item = _prepare(raw)
79
+ fmt = _resolve_format(item, output_type, leaf_name, format_overrides)
80
+ _save_item(slot_dir / f"{name}.{fmt}", item, fmt, visualization)
81
+ return
82
+
83
+ items = _unpack(data)
75
84
  for idx, item in enumerate(items):
76
85
  fmt = _resolve_format(item, output_type, leaf_name, format_overrides)
77
86
  _save_item(slot_dir / f"{idx:04d}.{fmt}", item, fmt, visualization)
@@ -375,6 +375,14 @@ class Run:
375
375
  aux=dict(transmission=t_map)),
376
376
  )
377
377
 
378
+ Slot values can also be dicts mapping custom string IDs to
379
+ items, producing named files instead of sequential indices::
380
+
381
+ run.save_outputs(
382
+ epoch=1, step=500,
383
+ rgb=dict(pred={"scene_042": img_a, "scene_117": img_b}),
384
+ )
385
+
378
386
  Accepted slot keys: ``pred``, ``gt``, ``input``, ``aux``.
379
387
  ``aux`` expects a sub-dict of named arrays.
380
388
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: euler-train
3
- Version: 2.4.1
3
+ Version: 2.5.0
4
4
  Summary: Lightweight file-based experiment logger for PyTorch
5
5
  Requires-Python: >=3.9
6
6
  Requires-Dist: numpy
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "euler-train"
7
- version = "2.4.1"
7
+ version = "2.5.0"
8
8
  description = "Lightweight file-based experiment logger for PyTorch"
9
9
  requires-python = ">=3.9"
10
10
  dependencies = ["numpy", "euler-dataset-contract"]
@@ -1444,6 +1444,42 @@ class TestSaveOutputsVariants:
1444
1444
  assert path.name == "epoch_2_step_500"
1445
1445
  run.finish()
1446
1446
 
1447
+ def test_dict_slot_produces_named_files(self, tmp_path):
1448
+ run = euler_train.init(dir=str(tmp_path / "r"), config={})
1449
+ a = np.zeros((4, 4, 3), dtype=np.uint8)
1450
+ b = np.ones((4, 4, 3), dtype=np.uint8) * 128
1451
+ run.save_outputs(epoch=0, step=0, rgb=dict(pred={"scene_a": a, "scene_b": b}))
1452
+
1453
+ pred_dir = run.dir / "outputs" / "epoch_0_step_0" / "rgb" / "pred"
1454
+ names = sorted(f.name for f in pred_dir.iterdir())
1455
+ assert names == ["scene_a.png", "scene_b.png"]
1456
+ run.finish()
1457
+
1458
+ def test_dict_slot_in_aux(self, tmp_path):
1459
+ run = euler_train.init(dir=str(tmp_path / "r"), config={})
1460
+ m1 = np.ones((4, 4), dtype=np.float32)
1461
+ m2 = np.zeros((4, 4), dtype=np.float32)
1462
+ run.save_outputs(
1463
+ epoch=0, step=0,
1464
+ depth=dict(aux=dict(attn={"head_0": m1, "head_1": m2})),
1465
+ )
1466
+
1467
+ attn_dir = run.dir / "outputs" / "epoch_0_step_0" / "depth" / "aux" / "attn"
1468
+ names = sorted(f.name for f in attn_dir.iterdir())
1469
+ assert names == ["head_0.npy", "head_1.npy"]
1470
+ run.finish()
1471
+
1472
+ def test_mixed_dict_and_array_slots(self, tmp_path):
1473
+ run = euler_train.init(dir=str(tmp_path / "r"), config={})
1474
+ a = np.zeros((4, 4, 3), dtype=np.uint8)
1475
+ run.save_outputs(epoch=0, step=0, rgb=dict(pred={"frame_x": a}, gt=a))
1476
+
1477
+ pred_dir = run.dir / "outputs" / "epoch_0_step_0" / "rgb" / "pred"
1478
+ gt_dir = run.dir / "outputs" / "epoch_0_step_0" / "rgb" / "gt"
1479
+ assert sorted(f.name for f in pred_dir.iterdir()) == ["frame_x.png"]
1480
+ assert sorted(f.name for f in gt_dir.iterdir()) == ["0000.png"]
1481
+ run.finish()
1482
+
1447
1483
  def test_returns_output_base_path(self, tmp_path):
1448
1484
  run = euler_train.init(dir=str(tmp_path / "r"), config={})
1449
1485
  arr = np.zeros((4, 4, 3), dtype=np.uint8)
File without changes
File without changes