Spaces:
Runtime error
Runtime error
Salman Khan
commited on
Commit
·
e4acaca
1
Parent(s):
eb6486f
Added brain tumor API project
Browse files- Dockerfile +26 -0
- newapi.py +107 -0
- requirements.txt +0 -0
- utils.py +25 -0
Dockerfile
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use an official Python runtime as a parent image
|
2 |
+
FROM python:3.10-slim
|
3 |
+
|
4 |
+
# Set environment variables
|
5 |
+
ENV PYTHONDONTWRITEBYTECODE=1
|
6 |
+
ENV PYTHONUNBUFFERED=1
|
7 |
+
|
8 |
+
# Set working directory
|
9 |
+
WORKDIR /app
|
10 |
+
|
11 |
+
# Install system dependencies
|
12 |
+
RUN apt-get update && apt-get install -y \
|
13 |
+
build-essential \
|
14 |
+
libgl1-mesa-glx \
|
15 |
+
&& rm -rf /var/lib/apt/lists/*
|
16 |
+
|
17 |
+
# Copy requirements and install
|
18 |
+
COPY requirements.txt .
|
19 |
+
RUN pip install --upgrade pip
|
20 |
+
RUN pip install -r requirements.txt
|
21 |
+
|
22 |
+
# Copy the rest of the app
|
23 |
+
COPY . .
|
24 |
+
|
25 |
+
# Set the command to run your FastAPI app with uvicorn
|
26 |
+
CMD ["uvicorn", "newapi:app", "--host", "0.0.0.0", "--port", "8080"]
|
newapi.py
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI, File, UploadFile
|
2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
3 |
+
from pydantic import BaseModel
|
4 |
+
import torch
|
5 |
+
from torchvision import transforms
|
6 |
+
from PIL import Image
|
7 |
+
import io
|
8 |
+
from huggingface_hub import hf_hub_download
|
9 |
+
|
10 |
+
from models.TumorModel import TumorClassification, GliomaStageModel
|
11 |
+
from utils import get_precautions_from_gemini
|
12 |
+
|
13 |
+
# Initialize FastAPI app
|
14 |
+
app = FastAPI(title="Brain Tumor Detection API")
|
15 |
+
|
16 |
+
# Enable CORS for all origins (adjust for production)
|
17 |
+
app.add_middleware(
|
18 |
+
CORSMiddleware,
|
19 |
+
allow_origins=["*"],
|
20 |
+
allow_credentials=True,
|
21 |
+
allow_methods=["*"],
|
22 |
+
allow_headers=["*"],
|
23 |
+
)
|
24 |
+
|
25 |
+
# Load Tumor Classification Model from Hugging Face
|
26 |
+
btd_model_path = hf_hub_download(
|
27 |
+
repo_id="Codewithsalty/brain-tumor-models",
|
28 |
+
filename="BTD_model.pth"
|
29 |
+
)
|
30 |
+
tumor_model = TumorClassification()
|
31 |
+
tumor_model.load_state_dict(torch.load(btd_model_path, map_location="cpu"))
|
32 |
+
tumor_model.eval()
|
33 |
+
|
34 |
+
# Load Glioma Stage Prediction Model from Hugging Face
|
35 |
+
glioma_model_path = hf_hub_download(
|
36 |
+
repo_id="Codewithsalty/brain-tumor-models",
|
37 |
+
filename="glioma_stages.pth"
|
38 |
+
)
|
39 |
+
glioma_model = GliomaStageModel()
|
40 |
+
glioma_model.load_state_dict(torch.load(glioma_model_path, map_location="cpu"))
|
41 |
+
glioma_model.eval()
|
42 |
+
|
43 |
+
# Image preprocessing pipeline
|
44 |
+
transform = transforms.Compose([
|
45 |
+
transforms.Grayscale(),
|
46 |
+
transforms.Resize((224, 224)),
|
47 |
+
transforms.ToTensor(),
|
48 |
+
transforms.Normalize(mean=[0.5], std=[0.5]),
|
49 |
+
])
|
50 |
+
|
51 |
+
# Health check endpoint
|
52 |
+
@app.get("/")
|
53 |
+
async def root():
|
54 |
+
return {"message": "Brain Tumor Detection API is running."}
|
55 |
+
|
56 |
+
# Tumor type labels
|
57 |
+
labels = ['glioma', 'meningioma', 'notumor', 'pituitary']
|
58 |
+
|
59 |
+
# Predict tumor type from uploaded image
|
60 |
+
@app.post("/predict-image")
|
61 |
+
async def predict_image(file: UploadFile = File(...)):
|
62 |
+
img_bytes = await file.read()
|
63 |
+
img = Image.open(io.BytesIO(img_bytes)).convert("L") # Ensure grayscale
|
64 |
+
x = transform(img).unsqueeze(0)
|
65 |
+
|
66 |
+
with torch.no_grad():
|
67 |
+
out = tumor_model(x)
|
68 |
+
idx = torch.argmax(out, dim=1).item()
|
69 |
+
tumor_type = labels[idx]
|
70 |
+
|
71 |
+
if tumor_type == "glioma":
|
72 |
+
return {"tumor_type": tumor_type, "next": "submit_mutation_data"}
|
73 |
+
else:
|
74 |
+
precautions = get_precautions_from_gemini(tumor_type)
|
75 |
+
return {"tumor_type": tumor_type, "precaution": precautions}
|
76 |
+
|
77 |
+
# Input model for glioma mutation data
|
78 |
+
class MutationInput(BaseModel):
|
79 |
+
gender: str
|
80 |
+
age: float
|
81 |
+
idh1: int
|
82 |
+
tp53: int
|
83 |
+
atrx: int
|
84 |
+
pten: int
|
85 |
+
egfr: int
|
86 |
+
cic: int
|
87 |
+
pik3ca: int
|
88 |
+
|
89 |
+
# Predict glioma stage based on mutations
|
90 |
+
@app.post("/predict-glioma-stage")
|
91 |
+
async def predict_glioma_stage(data: MutationInput):
|
92 |
+
gender_val = 0 if data.gender.lower() == 'm' else 1
|
93 |
+
features = [
|
94 |
+
gender_val, data.age, data.idh1, data.tp53, data.atrx,
|
95 |
+
data.pten, data.egfr, data.cic, data.pik3ca
|
96 |
+
]
|
97 |
+
x = torch.tensor(features).float().unsqueeze(0)
|
98 |
+
|
99 |
+
with torch.no_grad():
|
100 |
+
out = glioma_model(x)
|
101 |
+
idx = torch.argmax(out, dim=1).item()
|
102 |
+
stages = ['Stage 1', 'Stage 2', 'Stage 3', 'Stage 4']
|
103 |
+
return {"glioma_stage": stages[idx]}
|
104 |
+
|
105 |
+
if __name__ == "__main__":
|
106 |
+
import uvicorn
|
107 |
+
uvicorn.run("newapi:app", host="0.0.0.0", port=10000)
|
requirements.txt
ADDED
Binary file (176 Bytes). View file
|
|
utils.py
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
def get_user_test_data():
|
2 |
+
print("Enter the following details for prediction:")
|
3 |
+
|
4 |
+
gender_input = input("Gender (M/F): ").strip().lower()
|
5 |
+
gender = 0 if gender_input == 'm' else 1 # Male = 0, Female = 1
|
6 |
+
|
7 |
+
age = float(input("Age at Diagnosis: "))
|
8 |
+
|
9 |
+
idh1 = int(input("IDH1 Mutation? (1 for Yes, 0 for No): "))
|
10 |
+
tp53 = int(input("TP53 Mutation? (1 for Yes, 0 for No): "))
|
11 |
+
atrx = int(input("ATRX Mutation? (1 for Yes, 0 for No): "))
|
12 |
+
pten = int(input("PTEN Mutation? (1 for Yes, 0 for No): "))
|
13 |
+
egfr = int(input("EGFR Mutation? (1 for Yes, 0 for No): "))
|
14 |
+
cic = int(input("CIC Mutation? (1 for Yes, 0 for No): "))
|
15 |
+
pik3ca = int(input("PIK3CA Mutation? (1 for Yes, 0 for No): "))
|
16 |
+
|
17 |
+
return [gender, age, idh1, tp53, atrx, pten, egfr, cic, pik3ca]
|
18 |
+
|
19 |
+
def get_precautions_from_gemini(tumor_type):
|
20 |
+
precaution_db = {
|
21 |
+
"meningioma": "Avoid radiation exposure and get regular check-ups.",
|
22 |
+
"pituitary": "Monitor hormonal levels and follow medication strictly.",
|
23 |
+
"notumor": "Stay healthy and get annual MRI scans if symptoms appear."
|
24 |
+
}
|
25 |
+
return precaution_db.get(tumor_type, "No specific precautions found.")
|