euler-eval 2.9.0__tar.gz → 2.10.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_eval-2.9.0 → euler_eval-2.10.0}/PKG-INFO +5 -3
- {euler_eval-2.9.0 → euler_eval-2.10.0}/README.md +4 -2
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/cli.py +43 -4
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/data.py +6 -5
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval.egg-info/PKG-INFO +5 -3
- {euler_eval-2.9.0 → euler_eval-2.10.0}/pyproject.toml +1 -1
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_config.py +25 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_data_builders.py +23 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_save_results.py +15 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/__init__.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/evaluate.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/__init__.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/absrel.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/daniel_error.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/depth_binned_error.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/depth_edge_f1.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/depth_standard.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/fid_kid.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/gpu_depth_batch.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/gpu_image_batch.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/high_freq_energy.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/lpips_metric.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/normal_consistency.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/psnr.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/rgb_edge_f1.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/rgb_lpips.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/rgb_psnr_ssim.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/rho_a.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/rmse.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/scale_invariant_log.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/ssim.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/tail_errors.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/metrics/utils.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/sanity_checker.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval/utils/hierarchy_parser.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval.egg-info/SOURCES.txt +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval.egg-info/dependency_links.txt +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval.egg-info/entry_points.txt +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval.egg-info/requires.txt +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/euler_eval.egg-info/top_level.txt +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/init_cache.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/setup.cfg +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_alignment.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_cli_device.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_data.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_depth_alignment_output.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_depth_standard.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_evaluate_helpers.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_init_cache.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_integration.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_meta_output.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_metrics_utils.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_rgb_fid_output.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_rho_a.py +0 -0
- {euler_eval-2.9.0 → euler_eval-2.10.0}/tests/test_sparse_depth.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: euler-eval
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.10.0
|
|
4
4
|
Summary: Depth map evaluation toolkit with comprehensive metrics
|
|
5
5
|
Author: Depth Eval Contributors
|
|
6
6
|
License: MIT
|
|
@@ -239,7 +239,7 @@ Defines GT modalities, prediction datasets to evaluate, and optional euler_train
|
|
|
239
239
|
}
|
|
240
240
|
```
|
|
241
241
|
|
|
242
|
-
Each modality entry can optionally include a `split` field to select a specific split from the dataset (e.g. `{ "path": "/data/gt/depth", "split": "test" }`).
|
|
242
|
+
Each modality entry can optionally include a `split` field to select a specific split from the dataset (e.g. `{ "path": "/data/gt/depth", "split": "test" }`). euler-loading inline selectors are also accepted in `path`, such as `/data/muses.zip:test` or `/data/muses.zip:test#scope=rgb`.
|
|
243
243
|
|
|
244
244
|
For sparse pointcloud depth evaluation, use `gt.sparse_depth` instead of `gt.depth`. The prediction still uses `datasets[].depth` because the model output is a dense depth map. The evaluator projects the sparse GT point cloud into the prediction image plane using `gt.intrinsics` and `gt.camera_extrinsics`, then computes pointwise depth metrics only at projected valid pixels.
|
|
245
245
|
|
|
@@ -293,7 +293,7 @@ Dataset metadata (e.g. `radial_depth`, `rgb_range`, sparse point columns, and co
|
|
|
293
293
|
|
|
294
294
|
### Dataset Metadata
|
|
295
295
|
|
|
296
|
-
Each dataset directory must contain ds-crawler metadata artifacts, typically generated under `.ds_crawler/`:
|
|
296
|
+
Each dataset directory or archive must contain ds-crawler metadata artifacts, typically generated under `.ds_crawler/`:
|
|
297
297
|
|
|
298
298
|
```text
|
|
299
299
|
dataset-root/
|
|
@@ -303,6 +303,8 @@ dataset-root/
|
|
|
303
303
|
index.json
|
|
304
304
|
```
|
|
305
305
|
|
|
306
|
+
When one physical root or archive contains several logical modalities, the artifacts may instead be scoped under `.ds_crawler/<modality>/` with a `.ds_crawler/scopes.json` manifest. `euler-eval` passes modality scopes to euler-loading so paths such as `/data/muses.zip:test` can load `.ds_crawler/rgb/index.json`, `.ds_crawler/depth/index.json`, and related scoped artifacts from the same archive.
|
|
307
|
+
|
|
306
308
|
GT and prediction datasets are matched by hierarchy path and file ID through `MultiModalDataset`.
|
|
307
309
|
|
|
308
310
|
### `metrics_config.json`
|
|
@@ -201,7 +201,7 @@ Defines GT modalities, prediction datasets to evaluate, and optional euler_train
|
|
|
201
201
|
}
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
Each modality entry can optionally include a `split` field to select a specific split from the dataset (e.g. `{ "path": "/data/gt/depth", "split": "test" }`).
|
|
204
|
+
Each modality entry can optionally include a `split` field to select a specific split from the dataset (e.g. `{ "path": "/data/gt/depth", "split": "test" }`). euler-loading inline selectors are also accepted in `path`, such as `/data/muses.zip:test` or `/data/muses.zip:test#scope=rgb`.
|
|
205
205
|
|
|
206
206
|
For sparse pointcloud depth evaluation, use `gt.sparse_depth` instead of `gt.depth`. The prediction still uses `datasets[].depth` because the model output is a dense depth map. The evaluator projects the sparse GT point cloud into the prediction image plane using `gt.intrinsics` and `gt.camera_extrinsics`, then computes pointwise depth metrics only at projected valid pixels.
|
|
207
207
|
|
|
@@ -255,7 +255,7 @@ Dataset metadata (e.g. `radial_depth`, `rgb_range`, sparse point columns, and co
|
|
|
255
255
|
|
|
256
256
|
### Dataset Metadata
|
|
257
257
|
|
|
258
|
-
Each dataset directory must contain ds-crawler metadata artifacts, typically generated under `.ds_crawler/`:
|
|
258
|
+
Each dataset directory or archive must contain ds-crawler metadata artifacts, typically generated under `.ds_crawler/`:
|
|
259
259
|
|
|
260
260
|
```text
|
|
261
261
|
dataset-root/
|
|
@@ -265,6 +265,8 @@ dataset-root/
|
|
|
265
265
|
index.json
|
|
266
266
|
```
|
|
267
267
|
|
|
268
|
+
When one physical root or archive contains several logical modalities, the artifacts may instead be scoped under `.ds_crawler/<modality>/` with a `.ds_crawler/scopes.json` manifest. `euler-eval` passes modality scopes to euler-loading so paths such as `/data/muses.zip:test` can load `.ds_crawler/rgb/index.json`, `.ds_crawler/depth/index.json`, and related scoped artifacts from the same archive.
|
|
269
|
+
|
|
268
270
|
GT and prediction datasets are matched by hierarchy path and file ID through `MultiModalDataset`.
|
|
269
271
|
|
|
270
272
|
### `metrics_config.json`
|
|
@@ -13,6 +13,7 @@ import zipfile
|
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
|
|
15
15
|
import torch
|
|
16
|
+
from euler_loading import Modality
|
|
16
17
|
|
|
17
18
|
from .data import (
|
|
18
19
|
build_depth_eval_dataset,
|
|
@@ -40,6 +41,22 @@ except ImportError:
|
|
|
40
41
|
from euler_metric_naming import AxisDeclaration, MetricDescription, MetricNamespace
|
|
41
42
|
|
|
42
43
|
|
|
44
|
+
def _normalize_modality_path(
|
|
45
|
+
path: str | Path,
|
|
46
|
+
*,
|
|
47
|
+
modality_key: str,
|
|
48
|
+
split: str | None = None,
|
|
49
|
+
) -> Path:
|
|
50
|
+
"""Return the filesystem/archive root for an euler-loading modality path."""
|
|
51
|
+
modality = Modality(
|
|
52
|
+
str(path),
|
|
53
|
+
modality_type=modality_key,
|
|
54
|
+
metadata_scope=modality_key,
|
|
55
|
+
split=split,
|
|
56
|
+
)
|
|
57
|
+
return Path(modality.path)
|
|
58
|
+
|
|
59
|
+
|
|
43
60
|
# ── Eval namespace ──────────────────────────────────────────────────────────
|
|
44
61
|
# MetricNamespace subclass for eval context with custom axis declarations,
|
|
45
62
|
# following the Normed Metric Namespacing convention (§3.6, §4, §5.2).
|
|
@@ -599,7 +616,11 @@ def validate_gt_config(gt: dict) -> None:
|
|
|
599
616
|
"camera_extrinsics",
|
|
600
617
|
):
|
|
601
618
|
if modality in gt and "path" in gt[modality]:
|
|
602
|
-
p =
|
|
619
|
+
p = _normalize_modality_path(
|
|
620
|
+
gt[modality]["path"],
|
|
621
|
+
modality_key=modality,
|
|
622
|
+
split=gt[modality].get("split"),
|
|
623
|
+
)
|
|
603
624
|
if not p.exists():
|
|
604
625
|
raise ValueError(f"gt.{modality}.path does not exist: {p}")
|
|
605
626
|
|
|
@@ -624,7 +645,11 @@ def validate_dataset_entry(entry: dict, index: int) -> None:
|
|
|
624
645
|
|
|
625
646
|
for modality in ("rgb", "depth", "rays"):
|
|
626
647
|
if modality in entry and "path" in entry[modality]:
|
|
627
|
-
p =
|
|
648
|
+
p = _normalize_modality_path(
|
|
649
|
+
entry[modality]["path"],
|
|
650
|
+
modality_key=modality,
|
|
651
|
+
split=entry[modality].get("split"),
|
|
652
|
+
)
|
|
628
653
|
if not p.exists():
|
|
629
654
|
raise ValueError(f"{label}.{modality}.path does not exist: {p}")
|
|
630
655
|
|
|
@@ -749,12 +774,26 @@ def save_results(
|
|
|
749
774
|
and modality in dataset_config
|
|
750
775
|
and "path" in dataset_config[modality]
|
|
751
776
|
):
|
|
752
|
-
output_file =
|
|
777
|
+
output_file = (
|
|
778
|
+
_normalize_modality_path(
|
|
779
|
+
dataset_config[modality]["path"],
|
|
780
|
+
modality_key=modality,
|
|
781
|
+
split=dataset_config[modality].get("split"),
|
|
782
|
+
)
|
|
783
|
+
/ "eval.json"
|
|
784
|
+
)
|
|
753
785
|
else:
|
|
754
786
|
# Default: save alongside first available modality path
|
|
755
787
|
for mod in ("depth", "rgb", "rays"):
|
|
756
788
|
if mod in dataset_config and "path" in dataset_config[mod]:
|
|
757
|
-
output_file =
|
|
789
|
+
output_file = (
|
|
790
|
+
_normalize_modality_path(
|
|
791
|
+
dataset_config[mod]["path"],
|
|
792
|
+
modality_key=mod,
|
|
793
|
+
split=dataset_config[mod].get("split"),
|
|
794
|
+
)
|
|
795
|
+
/ "eval.json"
|
|
796
|
+
)
|
|
758
797
|
break
|
|
759
798
|
if output_file is None:
|
|
760
799
|
output_file = Path("eval.json")
|
|
@@ -525,13 +525,14 @@ def _resolve_sky_mask_loader(segmentation_path: str) -> Callable[..., Any]:
|
|
|
525
525
|
its ``sky_mask`` function so that raw class-segmentation data is
|
|
526
526
|
converted to a boolean sky mask at load time.
|
|
527
527
|
"""
|
|
528
|
+
modality = _modality(path=segmentation_path, modality_key="segmentation")
|
|
528
529
|
try:
|
|
529
530
|
index = index_dataset_from_path(
|
|
530
|
-
|
|
531
|
-
metadata_scope=
|
|
531
|
+
modality.path,
|
|
532
|
+
metadata_scope=modality.metadata_scope,
|
|
532
533
|
)
|
|
533
534
|
except FileNotFoundError:
|
|
534
|
-
index = index_dataset_from_path(
|
|
535
|
+
index = index_dataset_from_path(modality.path)
|
|
535
536
|
# Resolve euler_loading metadata the same way euler-loading does:
|
|
536
537
|
# try the contract addon API first (handles addons.euler_loading),
|
|
537
538
|
# then fall back to top-level euler_loading for legacy indices.
|
|
@@ -546,14 +547,14 @@ def _resolve_sky_mask_loader(segmentation_path: str) -> Callable[..., Any]:
|
|
|
546
547
|
loader_name = euler_meta.get("loader")
|
|
547
548
|
if loader_name is None:
|
|
548
549
|
raise ValueError(
|
|
549
|
-
f"Segmentation dataset at {
|
|
550
|
+
f"Segmentation dataset at {modality.path!r} does not declare "
|
|
550
551
|
f"an 'euler_loading.loader' in its ds-crawler index."
|
|
551
552
|
)
|
|
552
553
|
module = resolve_loader_module(loader_name)
|
|
553
554
|
sky_fn = getattr(module, "sky_mask", None)
|
|
554
555
|
if sky_fn is None or not callable(sky_fn):
|
|
555
556
|
raise ValueError(
|
|
556
|
-
f"Loader module {loader_name!r} (resolved from {
|
|
557
|
+
f"Loader module {loader_name!r} (resolved from {modality.path!r}) "
|
|
557
558
|
f"does not expose a 'sky_mask' function."
|
|
558
559
|
)
|
|
559
560
|
return sky_fn
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: euler-eval
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.10.0
|
|
4
4
|
Summary: Depth map evaluation toolkit with comprehensive metrics
|
|
5
5
|
Author: Depth Eval Contributors
|
|
6
6
|
License: MIT
|
|
@@ -239,7 +239,7 @@ Defines GT modalities, prediction datasets to evaluate, and optional euler_train
|
|
|
239
239
|
}
|
|
240
240
|
```
|
|
241
241
|
|
|
242
|
-
Each modality entry can optionally include a `split` field to select a specific split from the dataset (e.g. `{ "path": "/data/gt/depth", "split": "test" }`).
|
|
242
|
+
Each modality entry can optionally include a `split` field to select a specific split from the dataset (e.g. `{ "path": "/data/gt/depth", "split": "test" }`). euler-loading inline selectors are also accepted in `path`, such as `/data/muses.zip:test` or `/data/muses.zip:test#scope=rgb`.
|
|
243
243
|
|
|
244
244
|
For sparse pointcloud depth evaluation, use `gt.sparse_depth` instead of `gt.depth`. The prediction still uses `datasets[].depth` because the model output is a dense depth map. The evaluator projects the sparse GT point cloud into the prediction image plane using `gt.intrinsics` and `gt.camera_extrinsics`, then computes pointwise depth metrics only at projected valid pixels.
|
|
245
245
|
|
|
@@ -293,7 +293,7 @@ Dataset metadata (e.g. `radial_depth`, `rgb_range`, sparse point columns, and co
|
|
|
293
293
|
|
|
294
294
|
### Dataset Metadata
|
|
295
295
|
|
|
296
|
-
Each dataset directory must contain ds-crawler metadata artifacts, typically generated under `.ds_crawler/`:
|
|
296
|
+
Each dataset directory or archive must contain ds-crawler metadata artifacts, typically generated under `.ds_crawler/`:
|
|
297
297
|
|
|
298
298
|
```text
|
|
299
299
|
dataset-root/
|
|
@@ -303,6 +303,8 @@ dataset-root/
|
|
|
303
303
|
index.json
|
|
304
304
|
```
|
|
305
305
|
|
|
306
|
+
When one physical root or archive contains several logical modalities, the artifacts may instead be scoped under `.ds_crawler/<modality>/` with a `.ds_crawler/scopes.json` manifest. `euler-eval` passes modality scopes to euler-loading so paths such as `/data/muses.zip:test` can load `.ds_crawler/rgb/index.json`, `.ds_crawler/depth/index.json`, and related scoped artifacts from the same archive.
|
|
307
|
+
|
|
306
308
|
GT and prediction datasets are matched by hierarchy path and file ID through `MultiModalDataset`.
|
|
307
309
|
|
|
308
310
|
### `metrics_config.json`
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Tests for main.py config validation."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import zipfile
|
|
4
5
|
import pytest
|
|
5
6
|
|
|
6
7
|
from euler_eval.cli import load_config, validate_dataset_entry, validate_gt_config
|
|
@@ -50,6 +51,20 @@ class TestValidateGtConfig:
|
|
|
50
51
|
gt = {"rgb": {"path": str(rgb_path)}}
|
|
51
52
|
validate_gt_config(gt)
|
|
52
53
|
|
|
54
|
+
def test_inline_zip_split_gt_path_is_valid(self, tmp_path):
|
|
55
|
+
rgb_path = tmp_path / "reference.zip"
|
|
56
|
+
with zipfile.ZipFile(rgb_path, "w") as zf:
|
|
57
|
+
zf.writestr("dummy.txt", "x")
|
|
58
|
+
gt = {"rgb": {"path": f"{rgb_path}:fog_day"}}
|
|
59
|
+
validate_gt_config(gt)
|
|
60
|
+
|
|
61
|
+
def test_inline_scope_gt_path_is_valid(self, tmp_path):
|
|
62
|
+
rgb_path = tmp_path / "reference.zip"
|
|
63
|
+
with zipfile.ZipFile(rgb_path, "w") as zf:
|
|
64
|
+
zf.writestr("dummy.txt", "x")
|
|
65
|
+
gt = {"rgb": {"path": f"{rgb_path}#scope=rgb"}}
|
|
66
|
+
validate_gt_config(gt)
|
|
67
|
+
|
|
53
68
|
def test_sparse_depth_requires_projection_modalities(self, tmp_path):
|
|
54
69
|
sparse_path = tmp_path / "sparse_depth"
|
|
55
70
|
sparse_path.mkdir()
|
|
@@ -132,6 +147,16 @@ class TestValidateDatasetEntry:
|
|
|
132
147
|
with pytest.raises(ValueError, match="does not exist"):
|
|
133
148
|
validate_dataset_entry(entry, 0)
|
|
134
149
|
|
|
150
|
+
def test_inline_zip_split_dataset_path_is_valid(self, tmp_path):
|
|
151
|
+
rgb_path = tmp_path / "prediction.zip"
|
|
152
|
+
with zipfile.ZipFile(rgb_path, "w") as zf:
|
|
153
|
+
zf.writestr("dummy.txt", "x")
|
|
154
|
+
entry = {
|
|
155
|
+
"name": "model_a",
|
|
156
|
+
"rgb": {"path": f"{rgb_path}:fog_day"},
|
|
157
|
+
}
|
|
158
|
+
validate_dataset_entry(entry, 0)
|
|
159
|
+
|
|
135
160
|
def test_index_in_error_message(self, tmp_path):
|
|
136
161
|
entry = {"name": "test"}
|
|
137
162
|
with pytest.raises(ValueError, match=r"datasets\[3\]"):
|
|
@@ -169,3 +169,26 @@ def test_sky_mask_loader_resolution_uses_segmentation_scope(monkeypatch):
|
|
|
169
169
|
assert calls == [
|
|
170
170
|
("/datasets/shared", {"metadata_scope": "segmentation"}),
|
|
171
171
|
]
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def test_sky_mask_loader_resolution_strips_inline_split(monkeypatch):
|
|
175
|
+
calls = []
|
|
176
|
+
|
|
177
|
+
def fake_index_dataset_from_path(path, **kwargs):
|
|
178
|
+
calls.append((path, kwargs))
|
|
179
|
+
return {"euler_loading": {"loader": "vkitti2"}}
|
|
180
|
+
|
|
181
|
+
def sky_mask(path, meta=None):
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
monkeypatch.setattr(data, "index_dataset_from_path", fake_index_dataset_from_path)
|
|
185
|
+
monkeypatch.setattr(
|
|
186
|
+
data,
|
|
187
|
+
"resolve_loader_module",
|
|
188
|
+
lambda name: SimpleNamespace(sky_mask=sky_mask),
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
assert data._resolve_sky_mask_loader("/datasets/shared.zip:fog_day") is sky_mask
|
|
192
|
+
assert calls == [
|
|
193
|
+
("/datasets/shared.zip", {"metadata_scope": "segmentation"}),
|
|
194
|
+
]
|
|
@@ -214,6 +214,21 @@ class TestSaveResultsZip:
|
|
|
214
214
|
stored = json.loads(zf.read("eval.json"))
|
|
215
215
|
assert stored == results
|
|
216
216
|
|
|
217
|
+
def test_inline_zip_split_writes_eval_json_into_zip(self, tmp_path):
|
|
218
|
+
zp = tmp_path / "dataset.zip"
|
|
219
|
+
with zipfile.ZipFile(zp, "w") as zf:
|
|
220
|
+
zf.writestr("image_001.png", b"\x89PNG")
|
|
221
|
+
|
|
222
|
+
results = {"depth": {"rmse": 0.42}}
|
|
223
|
+
config = {"name": "model", "depth": {"path": f"{zp}:fog_day"}}
|
|
224
|
+
out = save_results(results, config)
|
|
225
|
+
|
|
226
|
+
assert out == zp / "eval.json"
|
|
227
|
+
with zipfile.ZipFile(zp, "r") as zf:
|
|
228
|
+
assert "eval.json" in zf.namelist()
|
|
229
|
+
stored = json.loads(zf.read("eval.json"))
|
|
230
|
+
assert stored == results
|
|
231
|
+
|
|
217
232
|
def test_preserves_existing_zip_contents(self, tmp_path):
|
|
218
233
|
zp = tmp_path / "dataset.zip"
|
|
219
234
|
with zipfile.ZipFile(zp, "w") as zf:
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|