Spaces:
Sleeping
Sleeping
Upload main.py with huggingface_hub
Browse files
main.py
CHANGED
|
@@ -2,7 +2,12 @@
|
|
| 2 |
Blood-Brain Omics Benchmark API
|
| 3 |
|
| 4 |
FastAPI + DuckDB backend serving benchmark results.
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
Endpoints:
|
| 8 |
GET /api/v1/registry - Full registry metadata
|
|
@@ -22,6 +27,7 @@ Endpoints:
|
|
| 22 |
|
| 23 |
import json
|
| 24 |
import os
|
|
|
|
| 25 |
from typing import Optional
|
| 26 |
|
| 27 |
import duckdb
|
|
@@ -32,6 +38,13 @@ from fastapi.middleware.cors import CORSMiddleware
|
|
| 32 |
# Configuration
|
| 33 |
# =============================================================================
|
| 34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
DATA_DIR = os.environ.get(
|
| 36 |
"BENCHMARK_DATA_DIR",
|
| 37 |
os.path.join(os.path.dirname(__file__), "..", "data")
|
|
@@ -51,67 +64,67 @@ app.add_middleware(
|
|
| 51 |
)
|
| 52 |
|
| 53 |
# =============================================================================
|
| 54 |
-
# Startup:
|
| 55 |
# =============================================================================
|
| 56 |
|
| 57 |
db = None
|
| 58 |
registry = None
|
| 59 |
|
| 60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
@app.on_event("startup")
|
| 62 |
def startup():
|
| 63 |
global db, registry
|
| 64 |
|
| 65 |
-
#
|
| 66 |
-
registry_path = os.path.join(DATA_DIR, "benchmark_registry.json")
|
| 67 |
-
if os.path.exists(registry_path):
|
| 68 |
-
with open(registry_path) as f:
|
| 69 |
-
registry = json.load(f)
|
| 70 |
-
else:
|
| 71 |
-
registry = {"project": {}, "blood_platforms": {}, "brain_targets": {},
|
| 72 |
-
"phases": {}, "models": {}}
|
| 73 |
-
|
| 74 |
-
# Initialize DuckDB
|
| 75 |
db = duckdb.connect(":memory:")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
-
|
| 78 |
-
|
|
|
|
| 79 |
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
n = db.execute("SELECT COUNT(*) FROM results").fetchone()[0]
|
| 86 |
-
print(f"Loaded results: {n} rows")
|
| 87 |
-
else:
|
| 88 |
-
print(f"WARNING: {results_path} not found")
|
| 89 |
-
db.execute("""
|
| 90 |
-
CREATE TABLE results (
|
| 91 |
-
phase VARCHAR, blood_platform VARCHAR, brain_target VARCHAR,
|
| 92 |
-
target VARCHAR, model VARCHAR, h2h_pair VARCHAR,
|
| 93 |
-
temporal_bin VARCHAR, n_samples INT, n_features INT,
|
| 94 |
-
include_covariates BOOLEAN, r2 DOUBLE, pearson DOUBLE,
|
| 95 |
-
mse DOUBLE, mae DOUBLE
|
| 96 |
-
)
|
| 97 |
-
""")
|
| 98 |
-
|
| 99 |
-
if os.path.exists(features_path):
|
| 100 |
-
db.execute(f"""
|
| 101 |
-
CREATE TABLE features AS
|
| 102 |
-
SELECT * FROM read_parquet('{features_path}')
|
| 103 |
-
""")
|
| 104 |
-
n = db.execute("SELECT COUNT(*) FROM features").fetchone()[0]
|
| 105 |
-
print(f"Loaded features: {n} rows")
|
| 106 |
else:
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
|
|
|
|
|
|
| 115 |
|
| 116 |
|
| 117 |
# =============================================================================
|
|
|
|
| 2 |
Blood-Brain Omics Benchmark API
|
| 3 |
|
| 4 |
FastAPI + DuckDB backend serving benchmark results.
|
| 5 |
+
Queries Parquet files remotely via DuckDB httpfs — no data downloaded to disk.
|
| 6 |
+
DuckDB reads only the needed columns/row groups per query via HTTP range requests.
|
| 7 |
+
|
| 8 |
+
Data source modes (in priority order):
|
| 9 |
+
1. Remote: HF Dataset repo via httpfs (default, zero RAM footprint)
|
| 10 |
+
2. Local: files in BENCHMARK_DATA_DIR (for local dev)
|
| 11 |
|
| 12 |
Endpoints:
|
| 13 |
GET /api/v1/registry - Full registry metadata
|
|
|
|
| 27 |
|
| 28 |
import json
|
| 29 |
import os
|
| 30 |
+
import urllib.request
|
| 31 |
from typing import Optional
|
| 32 |
|
| 33 |
import duckdb
|
|
|
|
| 38 |
# Configuration
|
| 39 |
# =============================================================================
|
| 40 |
|
| 41 |
+
# HF Dataset repo for remote Parquet queries
|
| 42 |
+
HF_DATASET = os.environ.get(
|
| 43 |
+
"HF_DATASET", "stasaking/blood-brain-benchmark"
|
| 44 |
+
)
|
| 45 |
+
HF_BASE_URL = f"https://huggingface.co/datasets/{HF_DATASET}/resolve/main"
|
| 46 |
+
|
| 47 |
+
# Local fallback for dev
|
| 48 |
DATA_DIR = os.environ.get(
|
| 49 |
"BENCHMARK_DATA_DIR",
|
| 50 |
os.path.join(os.path.dirname(__file__), "..", "data")
|
|
|
|
| 64 |
)
|
| 65 |
|
| 66 |
# =============================================================================
|
| 67 |
+
# Startup: configure DuckDB with httpfs views or local tables
|
| 68 |
# =============================================================================
|
| 69 |
|
| 70 |
db = None
|
| 71 |
registry = None
|
| 72 |
|
| 73 |
|
| 74 |
+
def _resolve_parquet(filename: str) -> str:
|
| 75 |
+
"""Return remote URL or local path for a Parquet file."""
|
| 76 |
+
local_path = os.path.join(DATA_DIR, filename)
|
| 77 |
+
if os.path.exists(local_path):
|
| 78 |
+
return local_path
|
| 79 |
+
return f"{HF_BASE_URL}/{filename}"
|
| 80 |
+
|
| 81 |
+
|
| 82 |
@app.on_event("startup")
|
| 83 |
def startup():
|
| 84 |
global db, registry
|
| 85 |
|
| 86 |
+
# Initialize DuckDB with httpfs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
db = duckdb.connect(":memory:")
|
| 88 |
+
db.execute("INSTALL httpfs; LOAD httpfs;")
|
| 89 |
+
|
| 90 |
+
# Resolve data sources (remote or local)
|
| 91 |
+
results_src = _resolve_parquet("benchmark_results.parquet")
|
| 92 |
+
features_src = _resolve_parquet("feature_importance.parquet")
|
| 93 |
+
|
| 94 |
+
is_remote = results_src.startswith("http")
|
| 95 |
+
mode = "remote httpfs" if is_remote else "local files"
|
| 96 |
+
print(f"Data mode: {mode}")
|
| 97 |
+
|
| 98 |
+
# Create views that query Parquet directly (no data copied into RAM)
|
| 99 |
+
db.execute(f"""
|
| 100 |
+
CREATE VIEW results AS
|
| 101 |
+
SELECT * FROM read_parquet('{results_src}')
|
| 102 |
+
""")
|
| 103 |
+
db.execute(f"""
|
| 104 |
+
CREATE VIEW features AS
|
| 105 |
+
SELECT * FROM read_parquet('{features_src}')
|
| 106 |
+
""")
|
| 107 |
|
| 108 |
+
n_results = db.execute("SELECT COUNT(*) FROM results").fetchone()[0]
|
| 109 |
+
n_features = db.execute("SELECT COUNT(*) FROM features").fetchone()[0]
|
| 110 |
+
print(f"Views created: {n_results} results, {n_features} features")
|
| 111 |
|
| 112 |
+
# Load registry JSON (small file, always downloaded)
|
| 113 |
+
registry_local = os.path.join(DATA_DIR, "benchmark_registry.json")
|
| 114 |
+
if os.path.exists(registry_local):
|
| 115 |
+
with open(registry_local) as f:
|
| 116 |
+
registry = json.load(f)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
else:
|
| 118 |
+
# Download from HF
|
| 119 |
+
registry_url = f"{HF_BASE_URL}/benchmark_registry.json"
|
| 120 |
+
try:
|
| 121 |
+
with urllib.request.urlopen(registry_url) as resp:
|
| 122 |
+
registry = json.loads(resp.read().decode())
|
| 123 |
+
print(f"Downloaded registry from {registry_url}")
|
| 124 |
+
except Exception as e:
|
| 125 |
+
print(f"WARNING: Could not load registry: {e}")
|
| 126 |
+
registry = {"project": {}, "blood_platforms": {},
|
| 127 |
+
"brain_targets": {}, "phases": {}, "models": {}}
|
| 128 |
|
| 129 |
|
| 130 |
# =============================================================================
|