stasaking commited on
Commit
a911cbd
·
verified ·
1 Parent(s): d9e09df

Upload main.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. main.py +61 -48
main.py CHANGED
@@ -2,7 +2,12 @@
2
  Blood-Brain Omics Benchmark API
3
 
4
  FastAPI + DuckDB backend serving benchmark results.
5
- Loads Parquet files at startup and queries them via DuckDB in-memory.
 
 
 
 
 
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: load data into DuckDB
55
  # =============================================================================
56
 
57
  db = None
58
  registry = None
59
 
60
 
 
 
 
 
 
 
 
 
61
  @app.on_event("startup")
62
  def startup():
63
  global db, registry
64
 
65
- # Load registry
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
- results_path = os.path.join(DATA_DIR, "benchmark_results.parquet")
78
- features_path = os.path.join(DATA_DIR, "feature_importance.parquet")
 
79
 
80
- if os.path.exists(results_path):
81
- db.execute(f"""
82
- CREATE TABLE results AS
83
- SELECT * FROM read_parquet('{results_path}')
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
- print(f"WARNING: {features_path} not found")
108
- db.execute("""
109
- CREATE TABLE features (
110
- phase VARCHAR, blood_platform VARCHAR, brain_target VARCHAR,
111
- target VARCHAR, model VARCHAR, feature_name VARCHAR,
112
- importance DOUBLE, rank SMALLINT
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
  # =============================================================================