euler-train 2.4.1__tar.gz → 2.6.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.
- {euler_train-2.4.1 → euler_train-2.6.0}/PKG-INFO +1 -1
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/outputs.py +24 -5
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/run.py +51 -42
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train.egg-info/PKG-INFO +1 -1
- {euler_train-2.4.1 → euler_train-2.6.0}/pyproject.toml +1 -1
- {euler_train-2.4.1 → euler_train-2.6.0}/tests/test_runlog.py +199 -8
- {euler_train-2.4.1 → euler_train-2.6.0}/README.md +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/__init__.py +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/_dataset_contract.py +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/architecture.py +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/environment.py +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/git_info.py +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/serialization.py +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/slurm.py +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train/stream.py +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train.egg-info/SOURCES.txt +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train.egg-info/dependency_links.txt +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train.egg-info/requires.txt +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/euler_train.egg-info/top_level.txt +0 -0
- {euler_train-2.4.1 → euler_train-2.6.0}/setup.cfg +0 -0
|
@@ -18,7 +18,7 @@ def save_output_tree(
|
|
|
18
18
|
format_overrides: dict[str, str],
|
|
19
19
|
visualization_overrides: dict[str, Any],
|
|
20
20
|
output_type: str,
|
|
21
|
-
) ->
|
|
21
|
+
) -> dict[str, Any]:
|
|
22
22
|
"""Persist all slots (pred, gt, input, aux/…) for one *output_type*.
|
|
23
23
|
|
|
24
24
|
*slots* example::
|
|
@@ -28,7 +28,10 @@ def save_output_tree(
|
|
|
28
28
|
"gt": array,
|
|
29
29
|
"aux": {"transmission": array, "attention": array},
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
Returns a dict mapping slot keys to their manifest entries.
|
|
31
33
|
"""
|
|
34
|
+
manifest: dict[str, Any] = {}
|
|
32
35
|
for slot_name, data in slots.items():
|
|
33
36
|
if data is None:
|
|
34
37
|
continue
|
|
@@ -36,7 +39,7 @@ def save_output_tree(
|
|
|
36
39
|
for aux_name, aux_data in data.items():
|
|
37
40
|
if aux_data is None:
|
|
38
41
|
continue
|
|
39
|
-
_save_slot(
|
|
42
|
+
manifest[f"aux/{aux_name}"] = _save_slot(
|
|
40
43
|
type_dir / "aux" / aux_name,
|
|
41
44
|
aux_data,
|
|
42
45
|
output_type,
|
|
@@ -45,7 +48,7 @@ def save_output_tree(
|
|
|
45
48
|
visualization_overrides,
|
|
46
49
|
)
|
|
47
50
|
else:
|
|
48
|
-
_save_slot(
|
|
51
|
+
manifest[slot_name] = _save_slot(
|
|
49
52
|
type_dir / slot_name,
|
|
50
53
|
data,
|
|
51
54
|
output_type,
|
|
@@ -53,6 +56,7 @@ def save_output_tree(
|
|
|
53
56
|
format_overrides,
|
|
54
57
|
visualization_overrides,
|
|
55
58
|
)
|
|
59
|
+
return manifest
|
|
56
60
|
|
|
57
61
|
|
|
58
62
|
# ---------------------------------------------------------------------------
|
|
@@ -66,15 +70,30 @@ def _save_slot(
|
|
|
66
70
|
leaf_name: str,
|
|
67
71
|
format_overrides: dict[str, str],
|
|
68
72
|
visualization_overrides: dict[str, Any],
|
|
69
|
-
) ->
|
|
73
|
+
) -> dict[str, Any]:
|
|
74
|
+
"""Save items for one slot and return a manifest entry."""
|
|
70
75
|
slot_dir.mkdir(parents=True, exist_ok=True)
|
|
71
|
-
items = _unpack(data)
|
|
72
76
|
visualization = _resolve_visualization(
|
|
73
77
|
output_type, leaf_name, visualization_overrides,
|
|
74
78
|
)
|
|
79
|
+
|
|
80
|
+
# Dict with string keys → named outputs (e.g. {"scene_042": img}).
|
|
81
|
+
if isinstance(data, dict):
|
|
82
|
+
files: list[dict[str, Any]] = []
|
|
83
|
+
for name, raw in data.items():
|
|
84
|
+
item = _prepare(raw)
|
|
85
|
+
fmt = _resolve_format(item, output_type, leaf_name, format_overrides)
|
|
86
|
+
_save_item(slot_dir / f"{name}.{fmt}", item, fmt, visualization)
|
|
87
|
+
files.append({"sample_id": name, "filename": f"{name}.{fmt}", "format": fmt})
|
|
88
|
+
return {"id_mode": "named", "files": files}
|
|
89
|
+
|
|
90
|
+
items = _unpack(data)
|
|
91
|
+
files = []
|
|
75
92
|
for idx, item in enumerate(items):
|
|
76
93
|
fmt = _resolve_format(item, output_type, leaf_name, format_overrides)
|
|
77
94
|
_save_item(slot_dir / f"{idx:04d}.{fmt}", item, fmt, visualization)
|
|
95
|
+
files.append({"sample_id": idx, "filename": f"{idx:04d}.{fmt}", "format": fmt})
|
|
96
|
+
return {"id_mode": "indexed", "files": files}
|
|
78
97
|
|
|
79
98
|
|
|
80
99
|
# ---- normalisation -------------------------------------------------------
|
|
@@ -361,6 +361,7 @@ class Run:
|
|
|
361
361
|
*,
|
|
362
362
|
epoch: int | None = None,
|
|
363
363
|
step: int | None = None,
|
|
364
|
+
metadata: dict[str, Any] | None = None,
|
|
364
365
|
**output_types: dict[str, Any],
|
|
365
366
|
) -> Path:
|
|
366
367
|
"""Save prediction / ground-truth / auxiliary arrays to disk.
|
|
@@ -375,11 +376,34 @@ class Run:
|
|
|
375
376
|
aux=dict(transmission=t_map)),
|
|
376
377
|
)
|
|
377
378
|
|
|
379
|
+
Slot values can also be dicts mapping custom string IDs to
|
|
380
|
+
items, producing named files instead of sequential indices::
|
|
381
|
+
|
|
382
|
+
run.save_outputs(
|
|
383
|
+
epoch=1, step=500,
|
|
384
|
+
rgb=dict(pred={"scene_042": img_a, "scene_117": img_b}),
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
An optional *metadata* dict attaches source context (dataset,
|
|
388
|
+
split, etc.) to the manifest. The ``dataset`` key is required
|
|
389
|
+
when *metadata* is provided::
|
|
390
|
+
|
|
391
|
+
run.save_outputs(
|
|
392
|
+
epoch=1, step=500,
|
|
393
|
+
metadata={"dataset": "vkitti2", "split": "val"},
|
|
394
|
+
rgb=dict(pred=pred_img),
|
|
395
|
+
)
|
|
396
|
+
|
|
378
397
|
Accepted slot keys: ``pred``, ``gt``, ``input``, ``aux``.
|
|
379
398
|
``aux`` expects a sub-dict of named arrays.
|
|
380
399
|
|
|
381
400
|
Returns the directory that was written to.
|
|
382
401
|
"""
|
|
402
|
+
if metadata is not None:
|
|
403
|
+
if not isinstance(metadata.get("dataset"), str) or not metadata["dataset"].strip():
|
|
404
|
+
raise ValueError(
|
|
405
|
+
"metadata must include a non-empty 'dataset' string"
|
|
406
|
+
)
|
|
383
407
|
parts: list[str] = []
|
|
384
408
|
if epoch is not None:
|
|
385
409
|
parts.append(f"epoch_{epoch}")
|
|
@@ -388,21 +412,38 @@ class Run:
|
|
|
388
412
|
dirname = "_".join(parts) or "unspecified"
|
|
389
413
|
base = self.dir / "outputs" / dirname
|
|
390
414
|
|
|
415
|
+
manifest_types: dict[str, Any] = {}
|
|
391
416
|
for output_type, slots in output_types.items():
|
|
392
417
|
if slots is None:
|
|
393
418
|
continue
|
|
394
|
-
save_output_tree(
|
|
419
|
+
slot_manifest = save_output_tree(
|
|
395
420
|
base / output_type,
|
|
396
421
|
slots,
|
|
397
422
|
self._output_formats,
|
|
398
423
|
self._output_visualization,
|
|
399
424
|
output_type,
|
|
400
425
|
)
|
|
426
|
+
if slot_manifest:
|
|
427
|
+
manifest_types[output_type] = slot_manifest
|
|
428
|
+
if manifest_types:
|
|
429
|
+
manifest: dict[str, Any] = {
|
|
430
|
+
"version": 1,
|
|
431
|
+
"epoch": epoch,
|
|
432
|
+
"step": step,
|
|
433
|
+
"output_types": manifest_types,
|
|
434
|
+
"format_overrides": dict(self._output_formats),
|
|
435
|
+
"visualization_overrides": {
|
|
436
|
+
k: dict(v) if isinstance(v, Mapping) else v
|
|
437
|
+
for k, v in self._output_visualization.items()
|
|
438
|
+
} if self._output_visualization else {},
|
|
439
|
+
}
|
|
440
|
+
if metadata is not None:
|
|
441
|
+
manifest["metadata"] = metadata
|
|
442
|
+
write_json(base / "manifest.json", manifest)
|
|
401
443
|
if base.exists():
|
|
402
444
|
self._record_artifact_update(base)
|
|
403
445
|
self._flush_meta()
|
|
404
|
-
|
|
405
|
-
if snapshot is not None:
|
|
446
|
+
if manifest_types and epoch is not None and step is not None:
|
|
406
447
|
self._emit_stream_event(
|
|
407
448
|
{
|
|
408
449
|
"type": "output_snapshot",
|
|
@@ -411,7 +452,13 @@ class Run:
|
|
|
411
452
|
epoch,
|
|
412
453
|
step,
|
|
413
454
|
),
|
|
414
|
-
"snapshot":
|
|
455
|
+
"snapshot": {
|
|
456
|
+
"version": 1,
|
|
457
|
+
"epoch": epoch,
|
|
458
|
+
"step": step,
|
|
459
|
+
"output_types": manifest_types,
|
|
460
|
+
**({"metadata": metadata} if metadata is not None else {}),
|
|
461
|
+
},
|
|
415
462
|
},
|
|
416
463
|
)
|
|
417
464
|
return base
|
|
@@ -880,44 +927,6 @@ class Run:
|
|
|
880
927
|
]
|
|
881
928
|
return tags or None
|
|
882
929
|
|
|
883
|
-
def _build_output_snapshot(
|
|
884
|
-
self,
|
|
885
|
-
epoch: int | None,
|
|
886
|
-
step: int | None,
|
|
887
|
-
output_types: dict[str, Any],
|
|
888
|
-
) -> dict[str, Any] | None:
|
|
889
|
-
if epoch is None or step is None:
|
|
890
|
-
return None
|
|
891
|
-
|
|
892
|
-
snapshot_types: dict[str, list[str]] = {}
|
|
893
|
-
for output_type, slots in output_types.items():
|
|
894
|
-
if slots is None or not isinstance(slots, Mapping):
|
|
895
|
-
continue
|
|
896
|
-
|
|
897
|
-
categories: list[str] = []
|
|
898
|
-
for slot_name, data in slots.items():
|
|
899
|
-
if data is None:
|
|
900
|
-
continue
|
|
901
|
-
if slot_name == "aux" and isinstance(data, Mapping):
|
|
902
|
-
for aux_name, aux_value in data.items():
|
|
903
|
-
if aux_value is None:
|
|
904
|
-
continue
|
|
905
|
-
categories.append(f"aux/{aux_name}")
|
|
906
|
-
else:
|
|
907
|
-
categories.append(str(slot_name))
|
|
908
|
-
|
|
909
|
-
if categories:
|
|
910
|
-
snapshot_types[str(output_type)] = sorted(set(categories))
|
|
911
|
-
|
|
912
|
-
if not snapshot_types:
|
|
913
|
-
return None
|
|
914
|
-
|
|
915
|
-
return {
|
|
916
|
-
"epoch": epoch,
|
|
917
|
-
"step": step,
|
|
918
|
-
"types": snapshot_types,
|
|
919
|
-
}
|
|
920
|
-
|
|
921
930
|
def _build_finish_patch(self) -> dict[str, Any]:
|
|
922
931
|
patch = {
|
|
923
932
|
"end_time": self._meta.get("end_time"),
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "euler-train"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.6.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)
|
|
@@ -1452,6 +1488,162 @@ class TestSaveOutputsVariants:
|
|
|
1452
1488
|
run.finish()
|
|
1453
1489
|
|
|
1454
1490
|
|
|
1491
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
1492
|
+
# Output manifest
|
|
1493
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
1494
|
+
|
|
1495
|
+
class TestSaveOutputsManifest:
|
|
1496
|
+
def test_manifest_written_for_basic_save(self, tmp_path):
|
|
1497
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1498
|
+
arr = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1499
|
+
run.save_outputs(epoch=1, step=500, rgb=dict(pred=arr))
|
|
1500
|
+
|
|
1501
|
+
m = _read_json(run.dir / "outputs" / "epoch_1_step_500" / "manifest.json")
|
|
1502
|
+
assert m["version"] == 1
|
|
1503
|
+
assert m["epoch"] == 1
|
|
1504
|
+
assert m["step"] == 500
|
|
1505
|
+
assert "rgb" in m["output_types"]
|
|
1506
|
+
assert "pred" in m["output_types"]["rgb"]
|
|
1507
|
+
run.finish()
|
|
1508
|
+
|
|
1509
|
+
def test_manifest_indexed_files(self, tmp_path):
|
|
1510
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1511
|
+
imgs = [np.zeros((4, 4, 3), dtype=np.uint8) for _ in range(3)]
|
|
1512
|
+
run.save_outputs(epoch=0, step=0, rgb=dict(pred=imgs))
|
|
1513
|
+
|
|
1514
|
+
slot = _read_json(
|
|
1515
|
+
run.dir / "outputs" / "epoch_0_step_0" / "manifest.json",
|
|
1516
|
+
)["output_types"]["rgb"]["pred"]
|
|
1517
|
+
assert slot["id_mode"] == "indexed"
|
|
1518
|
+
assert len(slot["files"]) == 3
|
|
1519
|
+
assert slot["files"][0] == {"sample_id": 0, "filename": "0000.png", "format": "png"}
|
|
1520
|
+
assert slot["files"][2]["sample_id"] == 2
|
|
1521
|
+
run.finish()
|
|
1522
|
+
|
|
1523
|
+
def test_manifest_named_files(self, tmp_path):
|
|
1524
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1525
|
+
a = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1526
|
+
run.save_outputs(epoch=0, step=0, rgb=dict(pred={"scene_a": a, "scene_b": a}))
|
|
1527
|
+
|
|
1528
|
+
slot = _read_json(
|
|
1529
|
+
run.dir / "outputs" / "epoch_0_step_0" / "manifest.json",
|
|
1530
|
+
)["output_types"]["rgb"]["pred"]
|
|
1531
|
+
assert slot["id_mode"] == "named"
|
|
1532
|
+
ids = [f["sample_id"] for f in slot["files"]]
|
|
1533
|
+
assert "scene_a" in ids
|
|
1534
|
+
assert "scene_b" in ids
|
|
1535
|
+
run.finish()
|
|
1536
|
+
|
|
1537
|
+
def test_manifest_aux_slots(self, tmp_path):
|
|
1538
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1539
|
+
arr = np.ones((4, 4), dtype=np.float32)
|
|
1540
|
+
run.save_outputs(epoch=0, step=0, depth=dict(aux=dict(transmission=arr)))
|
|
1541
|
+
|
|
1542
|
+
m = _read_json(run.dir / "outputs" / "epoch_0_step_0" / "manifest.json")
|
|
1543
|
+
assert "aux/transmission" in m["output_types"]["depth"]
|
|
1544
|
+
run.finish()
|
|
1545
|
+
|
|
1546
|
+
def test_manifest_none_slots_excluded(self, tmp_path):
|
|
1547
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1548
|
+
arr = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1549
|
+
run.save_outputs(epoch=0, step=0, rgb=dict(pred=arr, gt=None))
|
|
1550
|
+
|
|
1551
|
+
slots = _read_json(
|
|
1552
|
+
run.dir / "outputs" / "epoch_0_step_0" / "manifest.json",
|
|
1553
|
+
)["output_types"]["rgb"]
|
|
1554
|
+
assert "pred" in slots
|
|
1555
|
+
assert "gt" not in slots
|
|
1556
|
+
run.finish()
|
|
1557
|
+
|
|
1558
|
+
def test_manifest_records_format_overrides(self, tmp_path):
|
|
1559
|
+
run = euler_train.init(
|
|
1560
|
+
dir=str(tmp_path / "r"), config={},
|
|
1561
|
+
output_formats={"depth": "npz"},
|
|
1562
|
+
)
|
|
1563
|
+
arr = np.ones((4, 4), dtype=np.float32)
|
|
1564
|
+
run.save_outputs(epoch=0, step=0, depth=dict(pred=arr))
|
|
1565
|
+
|
|
1566
|
+
m = _read_json(run.dir / "outputs" / "epoch_0_step_0" / "manifest.json")
|
|
1567
|
+
assert m["format_overrides"] == {"depth": "npz"}
|
|
1568
|
+
assert m["output_types"]["depth"]["pred"]["files"][0]["format"] == "npz"
|
|
1569
|
+
run.finish()
|
|
1570
|
+
|
|
1571
|
+
def test_manifest_mixed_named_and_indexed(self, tmp_path):
|
|
1572
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1573
|
+
arr = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1574
|
+
run.save_outputs(epoch=0, step=0, rgb=dict(pred={"x": arr}, gt=arr))
|
|
1575
|
+
|
|
1576
|
+
slots = _read_json(
|
|
1577
|
+
run.dir / "outputs" / "epoch_0_step_0" / "manifest.json",
|
|
1578
|
+
)["output_types"]["rgb"]
|
|
1579
|
+
assert slots["pred"]["id_mode"] == "named"
|
|
1580
|
+
assert slots["gt"]["id_mode"] == "indexed"
|
|
1581
|
+
run.finish()
|
|
1582
|
+
|
|
1583
|
+
def test_manifest_metadata(self, tmp_path):
|
|
1584
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1585
|
+
arr = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1586
|
+
run.save_outputs(
|
|
1587
|
+
epoch=0, step=0,
|
|
1588
|
+
metadata={"dataset": "vkitti2", "split": "val"},
|
|
1589
|
+
rgb=dict(pred=arr),
|
|
1590
|
+
)
|
|
1591
|
+
|
|
1592
|
+
m = _read_json(run.dir / "outputs" / "epoch_0_step_0" / "manifest.json")
|
|
1593
|
+
assert m["metadata"] == {"dataset": "vkitti2", "split": "val"}
|
|
1594
|
+
run.finish()
|
|
1595
|
+
|
|
1596
|
+
def test_manifest_metadata_absent_when_not_provided(self, tmp_path):
|
|
1597
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1598
|
+
arr = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1599
|
+
run.save_outputs(epoch=0, step=0, rgb=dict(pred=arr))
|
|
1600
|
+
|
|
1601
|
+
m = _read_json(run.dir / "outputs" / "epoch_0_step_0" / "manifest.json")
|
|
1602
|
+
assert "metadata" not in m
|
|
1603
|
+
run.finish()
|
|
1604
|
+
|
|
1605
|
+
def test_manifest_metadata_requires_dataset(self, tmp_path):
|
|
1606
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1607
|
+
arr = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1608
|
+
with pytest.raises(ValueError, match="dataset"):
|
|
1609
|
+
run.save_outputs(
|
|
1610
|
+
epoch=0, step=0,
|
|
1611
|
+
metadata={"split": "val"},
|
|
1612
|
+
rgb=dict(pred=arr),
|
|
1613
|
+
)
|
|
1614
|
+
run.finish()
|
|
1615
|
+
|
|
1616
|
+
def test_manifest_metadata_rejects_empty_dataset(self, tmp_path):
|
|
1617
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1618
|
+
arr = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1619
|
+
with pytest.raises(ValueError, match="dataset"):
|
|
1620
|
+
run.save_outputs(
|
|
1621
|
+
epoch=0, step=0,
|
|
1622
|
+
metadata={"dataset": " "},
|
|
1623
|
+
rgb=dict(pred=arr),
|
|
1624
|
+
)
|
|
1625
|
+
run.finish()
|
|
1626
|
+
|
|
1627
|
+
def test_no_manifest_when_all_none(self, tmp_path):
|
|
1628
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1629
|
+
run.save_outputs(epoch=0, step=0, rgb=None, depth=None)
|
|
1630
|
+
|
|
1631
|
+
manifest_path = run.dir / "outputs" / "epoch_0_step_0" / "manifest.json"
|
|
1632
|
+
assert not manifest_path.exists()
|
|
1633
|
+
run.finish()
|
|
1634
|
+
|
|
1635
|
+
def test_manifest_multiple_output_types(self, tmp_path):
|
|
1636
|
+
run = euler_train.init(dir=str(tmp_path / "r"), config={})
|
|
1637
|
+
img = np.zeros((4, 4, 3), dtype=np.uint8)
|
|
1638
|
+
dep = np.ones((4, 4), dtype=np.float32)
|
|
1639
|
+
run.save_outputs(epoch=0, step=0, rgb=dict(pred=img), depth=dict(pred=dep))
|
|
1640
|
+
|
|
1641
|
+
m = _read_json(run.dir / "outputs" / "epoch_0_step_0" / "manifest.json")
|
|
1642
|
+
assert m["output_types"]["rgb"]["pred"]["files"][0]["format"] == "png"
|
|
1643
|
+
assert m["output_types"]["depth"]["pred"]["files"][0]["format"] == "npy"
|
|
1644
|
+
run.finish()
|
|
1645
|
+
|
|
1646
|
+
|
|
1455
1647
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
1456
1648
|
# init_checkpoint_dir
|
|
1457
1649
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -1730,14 +1922,13 @@ class TestStreaming:
|
|
|
1730
1922
|
assert "elapsed_sec" not in val_event["records"][0]
|
|
1731
1923
|
|
|
1732
1924
|
snapshot_event = consumer.events[5]
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
}
|
|
1925
|
+
snapshot = snapshot_event["snapshot"]
|
|
1926
|
+
assert snapshot["version"] == 1
|
|
1927
|
+
assert snapshot["epoch"] == 0
|
|
1928
|
+
assert snapshot["step"] == 1
|
|
1929
|
+
assert set(snapshot["output_types"]) == {"rgb", "depth"}
|
|
1930
|
+
assert set(snapshot["output_types"]["rgb"]) == {"pred", "gt"}
|
|
1931
|
+
assert "aux/transmission" in snapshot["output_types"]["depth"]
|
|
1741
1932
|
|
|
1742
1933
|
checkpoint_event = consumer.events[6]
|
|
1743
1934
|
assert checkpoint_event["checkpoint"] == {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|