"""Download and prepare a small, provenance-tracked DAVIS 2D probe asset set.""" from __future__ import annotations import argparse import hashlib import json import os import stat import tempfile import zipfile from datetime import UTC, datetime from pathlib import Path, PurePosixPath from typing import Any import requests from PIL import Image ROOT = Path(__file__).resolve().parents[1] DATA_ROOT = ROOT / "data" / "vision_2d_probe" RAW_ROOT = DATA_ROOT / "raw" WEIGHTS_ROOT = DATA_ROOT / "weights" EXTRACT_ROOT = DATA_ROOT / "davis2017_trainval_480p" OUTPUT_ROOT = ROOT / "outputs" / "vision_2d_probe_assets_20260921" DAVIS_PAGE_URL = "https://davischallenge.org/davis2017/code.html" DAVIS_URL = ( "https://data.vision.ee.ethz.ch/csergi/share/davis/" "DAVIS-2017-trainval-480p.zip" ) DINO_PAGE_URL = "https://github.com/facebookresearch/dinov2" DINO_URL = ( "https://dl.fbaipublicfiles.com/dinov2/dinov2_vits14/" "dinov2_vits14_pretrain.pth" ) USER_AGENT = "Codex-2d-probe-audit/1.0" CHUNK_SIZE = 1024 * 1024 MAX_UNCOMPRESSED_BYTES = 10_000_000_000 EXPERIMENT_ALLOCATION_COUNTS = { "fit": 24, "discovery": 12, "validation": 16, "reserve": 8, } def utc_now() -> str: return datetime.now(UTC).isoformat() def sha256_file(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as handle: for chunk in iter(lambda: handle.read(CHUNK_SIZE), b""): digest.update(chunk) return digest.hexdigest() def response_headers(response: requests.Response) -> dict[str, Any]: return { "status_code": response.status_code, "content_length": response.headers.get("Content-Length"), "content_type": response.headers.get("Content-Type"), "etag": response.headers.get("ETag"), "last_modified": response.headers.get("Last-Modified"), "final_url": str(response.url), } def get_remote_headers(url: str) -> dict[str, Any]: headers = {"User-Agent": USER_AGENT} try: response = requests.head( url, headers=headers, allow_redirects=True, timeout=(20, 60), ) response.raise_for_status() return response_headers(response) except requests.RequestException as exc: return {"error": f"HEAD failed: {exc}"} def download(url: str, destination: Path) -> dict[str, Any]: destination.parent.mkdir(parents=True, exist_ok=True) remote = get_remote_headers(url) expected_size = None if remote.get("content_length"): try: expected_size = int(remote["content_length"]) except (TypeError, ValueError): expected_size = None if destination.exists(): actual_size = destination.stat().st_size if expected_size is not None and actual_size != expected_size: raise RuntimeError( f"Existing file has unexpected size: {destination} " f"({actual_size} != {expected_size})" ) return { "url": url, "destination": str(destination.relative_to(ROOT)), "downloaded": False, "size_bytes": actual_size, "sha256": sha256_file(destination), "remote": remote, "local_verified_against": "HTTP Content-Length when available; SHA-256 is local only", } headers = {"User-Agent": USER_AGENT} response = requests.get( url, headers=headers, allow_redirects=True, stream=True, timeout=(20, 120), ) response.raise_for_status() file_descriptor, temporary_name = tempfile.mkstemp( prefix=destination.name + ".", suffix=".part", dir=str(destination.parent), ) os.close(file_descriptor) temporary = Path(temporary_name) try: with temporary.open("wb") as handle: for chunk in response.iter_content(chunk_size=CHUNK_SIZE): if chunk: handle.write(chunk) handle.flush() os.fsync(handle.fileno()) actual_size = temporary.stat().st_size if expected_size is not None and actual_size != expected_size: raise RuntimeError( f"Downloaded size mismatch for {url}: {actual_size} != {expected_size}" ) os.replace(temporary, destination) except BaseException: temporary.unlink(missing_ok=True) raise return { "url": url, "destination": str(destination.relative_to(ROOT)), "downloaded": True, "size_bytes": destination.stat().st_size, "sha256": sha256_file(destination), "remote": response_headers(response), "local_verified_against": "HTTP Content-Length when available; SHA-256 is local only", } def is_symlink_member(info: zipfile.ZipInfo) -> bool: mode = (info.external_attr >> 16) & 0xFFFF return stat.S_ISLNK(mode) def safe_member_path(root: Path, member_name: str) -> Path: normalized = member_name.replace("\\", "/") member = PurePosixPath(normalized) if member.is_absolute() or any(part in ("", ".", "..") for part in member.parts): raise RuntimeError(f"Unsafe ZIP member path: {member_name!r}") if len(member.parts[0]) >= 2 and member.parts[0][1] == ":": raise RuntimeError(f"Drive-qualified ZIP member path: {member_name!r}") target = (root / Path(*member.parts)).resolve() root_resolved = root.resolve() if os.path.commonpath([str(root_resolved), str(target)]) != str(root_resolved): raise RuntimeError(f"ZIP member escapes extraction root: {member_name!r}") return target def safe_extract(archive: Path, destination: Path) -> dict[str, Any]: if destination.exists(): return { "extracted": False, "destination": str(destination.relative_to(ROOT)), "reason": "destination already exists", } destination.parent.mkdir(parents=True, exist_ok=True) staging = Path( tempfile.mkdtemp( prefix=destination.name + ".", suffix=".extracting", dir=str(destination.parent), ) ) try: with zipfile.ZipFile(archive) as handle: infos = handle.infolist() total_size = sum(info.file_size for info in infos if not info.is_dir()) if total_size > MAX_UNCOMPRESSED_BYTES: raise RuntimeError( f"ZIP expands beyond safety limit: {total_size} bytes" ) for info in infos: if is_symlink_member(info): raise RuntimeError(f"Symlink ZIP member rejected: {info.filename!r}") target = safe_member_path(staging, info.filename) if info.is_dir(): target.mkdir(parents=True, exist_ok=True) continue target.parent.mkdir(parents=True, exist_ok=True) with handle.open(info, "r") as source, target.open("wb") as sink: for chunk in iter(lambda: source.read(CHUNK_SIZE), b""): sink.write(chunk) os.replace(staging, destination) except BaseException: for child in sorted(staging.rglob("*"), reverse=True): if child.is_file() or child.is_symlink(): child.unlink(missing_ok=True) elif child.is_dir(): child.rmdir() staging.rmdir() raise return { "extracted": True, "destination": str(destination.relative_to(ROOT)), } def find_dataset_root(extracted: Path) -> Path: candidates = [extracted] candidates.extend(path for path in extracted.iterdir() if path.is_dir()) for candidate in candidates: if (candidate / "ImageSets" / "2017").is_dir(): return candidate raise RuntimeError(f"Could not locate DAVIS ImageSets/2017 under {extracted}") def resolve_media_dir(dataset_root: Path, dirname: str) -> Path: candidates = [dataset_root / dirname] candidates.extend(sorted(dataset_root.glob(f"{dirname}/*"))) for candidate in candidates: if not candidate.is_dir(): continue if any(child.is_dir() and any(child.glob("*.jpg" if dirname == "JPEGImages" else "*.png")) for child in candidate.iterdir()): return candidate raise RuntimeError(f"Could not locate {dirname} under {dataset_root}") def read_split(path: Path) -> list[str]: return [ line.strip() for line in path.read_text(encoding="utf-8").splitlines() if line.strip() and not line.lstrip().startswith("#") ] def stable_sequence_rank(name: str) -> str: """Return the deterministic UTF-8 name rank used for experiment allocation.""" return hashlib.sha256(name.encode("utf-8")).hexdigest() def build_experiment_allocation( train_names: list[str], val_names: list[str], ) -> dict[str, Any]: """Allocate only official train sequences and seal official val sequences.""" expected_train = sum(EXPERIMENT_ALLOCATION_COUNTS.values()) if len(train_names) != expected_train: raise RuntimeError( "Official train sequence count does not match the frozen allocation: " f"{len(train_names)} != {expected_train}" ) if len(val_names) != 30: raise RuntimeError( f"Official val sequence count changed: {len(val_names)} != 30" ) if len(set(train_names)) != len(train_names): raise RuntimeError("Official train split contains duplicate sequence names") if len(set(val_names)) != len(val_names): raise RuntimeError("Official val split contains duplicate sequence names") if set(train_names).intersection(val_names): raise RuntimeError("Official train/val splits overlap") ordered = sorted(train_names, key=stable_sequence_rank) groups: dict[str, dict[str, Any]] = {} offset = 0 for split, count in EXPERIMENT_ALLOCATION_COUNTS.items(): names = ordered[offset : offset + count] groups[split] = {"count": len(names), "sequence_names": names} offset += count return { "source_split": "official train.txt", "ordering": "ascending sha256(sequence_name encoded as UTF-8)", "counts": dict(EXPERIMENT_ALLOCATION_COUNTS), "groups": groups, "official_val": { "source_split": "official val.txt", "sequence_count": len(val_names), "sequence_names": val_names, "sealed": True, "used_for_experiment": False, }, } def sequence_record( dataset_root: Path, image_root: Path, mask_root: Path, name: str, ) -> dict[str, Any]: image_dir = image_root / name mask_dir = mask_root / name images = sorted(image_dir.glob("*.jpg")) masks = sorted(mask_dir.glob("*.png")) if not images: raise RuntimeError(f"No JPEG frames for sequence {name}") if not masks: raise RuntimeError(f"No PNG masks for sequence {name}") first_image = images[0] with Image.open(first_image) as image: width, height = image.size image_names = {path.stem for path in images} mask_names = {path.stem for path in masks} missing_masks = sorted(image_names - mask_names) return { "sequence": name, "image_dir": str(image_dir.relative_to(dataset_root)), "mask_dir": str(mask_dir.relative_to(dataset_root)), "frame_count": len(images), "mask_count": len(masks), "missing_mask_count": len(missing_masks), "first_frame": images[0].name, "last_frame": images[-1].name, "width": width, "height": height, } def build_dataset_manifest( archive_record: dict[str, Any], extraction_record: dict[str, Any], ) -> dict[str, Any]: dataset_root = find_dataset_root(EXTRACT_ROOT) image_root = resolve_media_dir(dataset_root, "JPEGImages") mask_root = resolve_media_dir(dataset_root, "Annotations") split_root = dataset_root / "ImageSets" / "2017" split_paths = { "train": split_root / "train.txt", "val": split_root / "val.txt", } if not split_paths["train"].exists() or not split_paths["val"].exists(): raise RuntimeError(f"Missing official train/val split files under {split_root}") split_names = {name: read_split(path) for name, path in split_paths.items()} overlap = sorted(set(split_names["train"]).intersection(split_names["val"])) if overlap: raise RuntimeError(f"Official train/val sequence overlap: {overlap[:5]}") records = { "train": [ sequence_record(dataset_root, image_root, mask_root, name) for name in split_names["train"] ], "val": [ {"sequence": name, "sealed": True} for name in split_names["val"] ], } total_sequences = len(set(split_names["train"]) | set(split_names["val"])) if total_sequences < 40: raise RuntimeError(f"Too few independent sequences: {total_sequences}") return { "dataset": "DAVIS-2017 trainval 480p", "official_page": DAVIS_PAGE_URL, "archive": archive_record, "extraction": extraction_record, "dataset_root": str(dataset_root.relative_to(ROOT)), "image_root": str(image_root.relative_to(dataset_root)), "mask_root": str(mask_root.relative_to(dataset_root)), "split_root": str(split_root.relative_to(dataset_root)), "split_policy": ( "official train.txt and val.txt are inventory splits; " "experimental allocation is recorded separately" ), "split_counts": {split: len(names) for split, names in split_names.items()}, "train_val_overlap": overlap, "sequences": records, } def write_json(path: Path, value: dict[str, Any]) -> None: path.parent.mkdir(parents=True, exist_ok=True) temporary = path.with_suffix(path.suffix + ".part") temporary.write_text( json.dumps(value, ensure_ascii=True, indent=2) + "\n", encoding="utf-8", ) os.replace(temporary, path) def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--skip-weights", action="store_true", help="Prepare DAVIS without downloading the DINOv2 checkpoint.", ) return parser.parse_args() def main() -> None: args = parse_args() run_started = utc_now() OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) log_path = OUTPUT_ROOT / "prepare.log" def log(message: str) -> None: line = f"[{utc_now()}] {message}\n" with log_path.open("a", encoding="utf-8") as handle: handle.write(line) print(line, end="") log("starting 2D probe asset preparation") archive_path = RAW_ROOT / Path(DAVIS_URL).name archive_record = download(DAVIS_URL, archive_path) log( f"DAVIS archive ready: {archive_record['size_bytes']} bytes " f"sha256={archive_record['sha256']}" ) extraction_record = safe_extract(archive_path, EXTRACT_ROOT) log(f"DAVIS extraction: {extraction_record}") weight_record: dict[str, Any] | None = None if not args.skip_weights: weight_path = WEIGHTS_ROOT / Path(DINO_URL).name weight_record = download(DINO_URL, weight_path) log( f"DINOv2 checkpoint ready: {weight_record['size_bytes']} bytes " f"sha256={weight_record['sha256']}" ) dataset_manifest = build_dataset_manifest(archive_record, extraction_record) experiment_allocation = build_experiment_allocation( [record["sequence"] for record in dataset_manifest["sequences"]["train"]], [record["sequence"] for record in dataset_manifest["sequences"]["val"]], ) manifest: dict[str, Any] = { "schema": "vision_2d_probe_assets.v1", "run_started_at": run_started, "run_finished_at": utc_now(), "project_root": str(ROOT), "provenance": { "local_sha256_note": ( "SHA-256 values were computed locally after download; " "no official checksum was asserted." ), "archive_source": DAVIS_URL, "archive_source_page": DAVIS_PAGE_URL, "checkpoint_source": DINO_URL if weight_record else None, "checkpoint_source_page": DINO_PAGE_URL if weight_record else None, }, "dataset": dataset_manifest, "experiment_allocation": experiment_allocation, "weights": weight_record, } write_json(OUTPUT_ROOT / "manifest.json", manifest) log( "completed: " f"train={manifest['dataset']['split_counts'].get('train', 0)} " f"val={manifest['dataset']['split_counts'].get('val', 0)}" ) if __name__ == "__main__": main()