Spaces:
Sleeping
Sleeping
Dan Vancea commited on
Commit ·
3269a5c
1
Parent(s): a635c41
Update call_models.py
Browse files- call_models.py +61 -0
call_models.py
CHANGED
|
@@ -3,14 +3,75 @@ from datetime import datetime
|
|
| 3 |
from flask import Flask, request, jsonify
|
| 4 |
from flask_cors import CORS
|
| 5 |
from dotenv import load_dotenv
|
|
|
|
| 6 |
|
| 7 |
from predict_from_supabase import predict_replacements
|
|
|
|
| 8 |
|
| 9 |
load_dotenv()
|
| 10 |
|
| 11 |
app = Flask(__name__)
|
| 12 |
CORS(app)
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
@app.route("/api/schedule", methods=["POST"])
|
| 16 |
def schedule():
|
|
|
|
| 3 |
from flask import Flask, request, jsonify
|
| 4 |
from flask_cors import CORS
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
+
import numpy as np
|
| 7 |
|
| 8 |
from predict_from_supabase import predict_replacements
|
| 9 |
+
from model import DegradationModel, COMPONENT_NAMES
|
| 10 |
|
| 11 |
load_dotenv()
|
| 12 |
|
| 13 |
app = Flask(__name__)
|
| 14 |
CORS(app)
|
| 15 |
|
| 16 |
+
# Load the default degradation model once at startup
|
| 17 |
+
_DEFAULT_MODEL_PATH = "model.npz"
|
| 18 |
+
_degradation_model: DegradationModel | None = None
|
| 19 |
+
|
| 20 |
+
def _get_model(path: str = _DEFAULT_MODEL_PATH) -> DegradationModel:
|
| 21 |
+
global _degradation_model
|
| 22 |
+
if _degradation_model is None:
|
| 23 |
+
_degradation_model = DegradationModel.load(path)
|
| 24 |
+
return _degradation_model
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
@app.route("/api/predict", methods=["POST"])
|
| 28 |
+
def predict():
|
| 29 |
+
data = request.json or {}
|
| 30 |
+
|
| 31 |
+
h0_raw = data.get("h0")
|
| 32 |
+
X_raw = data.get("X")
|
| 33 |
+
weeks = float(data.get("weeks", 6))
|
| 34 |
+
model_path = data.get("model_path", _DEFAULT_MODEL_PATH)
|
| 35 |
+
|
| 36 |
+
if h0_raw is None:
|
| 37 |
+
return jsonify({"error": "h0 (current health state) is required"}), 400
|
| 38 |
+
if X_raw is None:
|
| 39 |
+
return jsonify({"error": "X (input conditions) is required"}), 400
|
| 40 |
+
|
| 41 |
+
try:
|
| 42 |
+
model = _get_model(model_path)
|
| 43 |
+
except FileNotFoundError:
|
| 44 |
+
return jsonify({"error": f"model file not found: {model_path}"}), 404
|
| 45 |
+
|
| 46 |
+
h0 = np.array(h0_raw, dtype=float)
|
| 47 |
+
X = np.array(X_raw, dtype=float)
|
| 48 |
+
|
| 49 |
+
if h0.shape != (model.N,):
|
| 50 |
+
return jsonify({"error": f"h0 must have {model.N} elements, got {h0.shape}"}), 400
|
| 51 |
+
if X.shape != (model.C,):
|
| 52 |
+
return jsonify({"error": f"X must have {model.C} elements, got {X.shape}"}), 400
|
| 53 |
+
|
| 54 |
+
# Euler integration from h0, deterministic, 100 steps per week
|
| 55 |
+
tau_hours = weeks * 7 * 24.0
|
| 56 |
+
n_steps = int(weeks) * 20
|
| 57 |
+
dt = tau_hours / n_steps
|
| 58 |
+
steps_per_week = n_steps // int(weeks)
|
| 59 |
+
|
| 60 |
+
h = h0.copy()
|
| 61 |
+
weekly_snapshots = [h0.tolist()]
|
| 62 |
+
|
| 63 |
+
for step in range(1, n_steps + 1):
|
| 64 |
+
h = np.clip(h + dt * model.f(h, X), 0.0, 1.0)
|
| 65 |
+
if step % steps_per_week == 0:
|
| 66 |
+
weekly_snapshots.append(h.tolist())
|
| 67 |
+
|
| 68 |
+
return jsonify({
|
| 69 |
+
"component_names": COMPONENT_NAMES,
|
| 70 |
+
"weeks": weeks,
|
| 71 |
+
"weekly_health": weekly_snapshots, # index 0 = now, index k = after k weeks
|
| 72 |
+
"final_health": h.tolist(),
|
| 73 |
+
})
|
| 74 |
+
|
| 75 |
|
| 76 |
@app.route("/api/schedule", methods=["POST"])
|
| 77 |
def schedule():
|