Skip to content

download_cifar10dvs.py

CIFAR10-DVS dataset downloader - 131 lines. View on GitHub (image-neuro/download_cifar10dvs.py).

"""Download and inspect the CIFAR10-DVS dataset.

CIFAR10-DVS is the neuromorphic version of CIFAR-10, recorded by displaying
static images on a monitor and capturing with a DVS (Dynamic Vision Sensor)
camera at 128x128 resolution.

The download is ~650 MB from Figshare.  If it fails, the script retries
with a longer timeout.  You can also download manually from:
  https://figshare.com/articles/dataset/CIFAR10-DVS_New/8228398

Usage:
    uv run python image-neuro/download_cifar10dvs.py
"""

import os
import numpy as np
import tonic

SAVE_DIR = os.path.join("..", "assets")


def download_dataset():
    print("Loading CIFAR10-DVS...")

    # Check if already extracted  -  skip tonic's download/MD5 check
    dataset_dir = os.path.join(SAVE_DIR, "CIFAR10DVS")
    aedat4_count = (
        sum(1 for root, _, files in os.walk(dataset_dir) for f in files if f.endswith(".aedat4"))
        if os.path.isdir(dataset_dir)
        else 0
    )

    if aedat4_count >= 1000:
        print(f"  Found {aedat4_count} .aedat4 files, skipping download.")
        # Construct dataset without triggering download
        ds = tonic.datasets.CIFAR10DVS.__new__(tonic.datasets.CIFAR10DVS)
        ds.location_on_system = dataset_dir
        ds.transform = None
        ds.target_transform = None
        ds.transforms = None
        ds.data = []
        ds.targets = []
        ds.folder_name = ""

        for path, dirs, files in os.walk(dataset_dir):
            dirs.sort()
            for file in sorted(files):
                if file.endswith("aedat4"):
                    ds.data.append(os.path.join(path, file))
                    label_number = tonic.datasets.CIFAR10DVS.classes[os.path.basename(path)]
                    ds.targets.append(label_number)
        return ds

    # Fall back to tonic download
    print("  Extracted files not found, downloading (~650 MB)...\n")
    try:
        ds = tonic.datasets.CIFAR10DVS(save_to=SAVE_DIR)
    except Exception as e:
        print(f"  Download failed: {e}")
        print("\n  If the download times out, try downloading manually:")
        print("    1. Go to: https://figshare.com/ndownloader/files/38023437")
        print(f"    2. Save as: {os.path.join(dataset_dir, 'CIFAR10DVS.zip')}")
        print("    3. Re-run this script (it will extract automatically)")
        raise

    return ds


def inspect_dataset(ds):
    print(f"Samples: {len(ds)}")
    print(f"Sensor size: {ds.sensor_size}")

    classes = [
        "airplane",
        "automobile",
        "bird",
        "cat",
        "deer",
        "dog",
        "frog",
        "horse",
        "ship",
        "truck",
    ]
    print(f"Classes: {len(classes)}  -  {', '.join(classes)}")

    # Inspect a few samples
    print("\nSample statistics (first 50):")
    n_check = min(50, len(ds))
    event_counts = []
    durations = []
    for i in range(n_check):
        events, label = ds[i]
        event_counts.append(len(events))
        t = events["t"]
        durations.append((t.max() - t.min()) / 1e6)  # microseconds to seconds

    print(f"  Events/sample: mean={np.mean(event_counts):.0f}, min={np.min(event_counts)}, max={np.max(event_counts)}")
    print(f"  Duration: mean={np.mean(durations):.3f}s, min={np.min(durations):.3f}s, max={np.max(durations):.3f}s")

    # Show a single sample in detail
    events, label = ds[0]
    print("\nSample 0 detail:")
    print(f"  Label: {label} ({classes[label]})")
    print(f"  Events: {len(events)}")
    print(f"  Dtype: {events.dtype}")
    print(f"  Fields: {events.dtype.names}")
    print(f"  X range: {events['x'].min()}-{events['x'].max()}")
    print(f"  Y range: {events['y'].min()}-{events['y'].max()}")
    print(f"  Polarities: {np.unique(events['p'])}")
    print(f"  First 5 events: {events[:5]}")


def main():
    print("=" * 60)
    print("CIFAR10-DVS Dataset")
    print("  Source: Li et al. (Frontiers in Neuroscience, 2017)")
    print("  Encoding: DVS camera recording of static CIFAR-10 images")
    print("  Resolution: 128x128, 2 polarities")
    print("  Task: 10-class object classification")
    print("=" * 60)

    ds = download_dataset()
    inspect_dataset(ds)

    print(f"\nDone. Data saved to: {os.path.abspath(SAVE_DIR)}")


if __name__ == "__main__":
    main()