| """Download the Brain Tumor MRI dataset from Kaggle. |
| |
| Dataset: masoudnickparvar/brain-tumor-mri-dataset |
| Layout after extraction: |
| data/raw/Training/{glioma,meningioma,notumor,pituitary}/*.jpg |
| data/raw/Testing/{glioma,meningioma,notumor,pituitary}/*.jpg |
| |
| Prerequisites: |
| 1. Create a Kaggle account and an API token at https://www.kaggle.com/settings. |
| 2. Save the downloaded kaggle.json to ~/.kaggle/kaggle.json and chmod 600. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import os |
| import subprocess |
| import sys |
| from pathlib import Path |
|
|
| DATASET = "masoudnickparvar/brain-tumor-mri-dataset" |
| PROJECT_ROOT = Path(__file__).resolve().parent.parent |
| RAW_DIR = PROJECT_ROOT / "data" / "raw" |
| EXPECTED_CLASSES = {"glioma", "meningioma", "notumor", "pituitary"} |
|
|
|
|
| def ensure_kaggle_cli() -> None: |
| try: |
| subprocess.run( |
| ["kaggle", "--version"], check=True, capture_output=True, text=True |
| ) |
| except (subprocess.CalledProcessError, FileNotFoundError): |
| print("Kaggle CLI not found. Installing...") |
| subprocess.run([sys.executable, "-m", "pip", "install", "kaggle"], check=True) |
|
|
|
|
| def ensure_credentials() -> None: |
| cred = Path.home() / ".kaggle" / "kaggle.json" |
| if not cred.exists(): |
| sys.exit( |
| "\nMissing ~/.kaggle/kaggle.json.\n" |
| "Create one at https://www.kaggle.com/settings -> 'Create New Token'\n" |
| "then: mkdir -p ~/.kaggle && mv ~/Downloads/kaggle.json ~/.kaggle/ && chmod 600 ~/.kaggle/kaggle.json\n" |
| ) |
| |
| cred.chmod(0o600) |
|
|
|
|
| def already_downloaded() -> bool: |
| training = RAW_DIR / "Training" |
| testing = RAW_DIR / "Testing" |
| if not training.is_dir() or not testing.is_dir(): |
| return False |
| train_classes = {p.name for p in training.iterdir() if p.is_dir()} |
| test_classes = {p.name for p in testing.iterdir() if p.is_dir()} |
| return EXPECTED_CLASSES.issubset(train_classes) and EXPECTED_CLASSES.issubset( |
| test_classes |
| ) |
|
|
|
|
| def download() -> None: |
| RAW_DIR.mkdir(parents=True, exist_ok=True) |
| print(f"Downloading {DATASET} -> {RAW_DIR}") |
| subprocess.run( |
| [ |
| "kaggle", |
| "datasets", |
| "download", |
| "-d", |
| DATASET, |
| "-p", |
| str(RAW_DIR), |
| "--unzip", |
| ], |
| check=True, |
| ) |
|
|
|
|
| def summarize() -> None: |
| for split in ("Training", "Testing"): |
| split_dir = RAW_DIR / split |
| if not split_dir.is_dir(): |
| continue |
| print(f"\n{split}:") |
| for cls_dir in sorted(split_dir.iterdir()): |
| if cls_dir.is_dir(): |
| n = sum(1 for _ in cls_dir.iterdir()) |
| print(f" {cls_dir.name:12s} {n:5d} images") |
|
|
|
|
| def main() -> None: |
| if already_downloaded(): |
| print(f"Dataset already present at {RAW_DIR}. Skipping download.") |
| else: |
| ensure_kaggle_cli() |
| ensure_credentials() |
| download() |
| summarize() |
| print("\nDone.") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|