File size: 4,759 Bytes
ba6a669
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ab6d09e
 
 
 
ba6a669
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from flask import Flask, request, jsonify
import requests
import numpy as np
import pandas as pd
import tensorflow as tf
import joblib
import tifffile as tiff
import io
from datetime import datetime
import os

from utils import preprocess_tabular_data, load_image_as_array  # Pastikan ini tersedia

app = Flask(__name__)

@app.route("/")
def home():
    return "<h1>Welcome to the Flood Prediction API!</h1><p>Append /predict to the URL to make a prediction.</p>"

# Load model dengan signature
loaded = tf.saved_model.load("saved_model/")
infer = loaded.signatures["serving_default"]

# Load preprocessor
preprocessor = joblib.load("preprocessor.pkl")


def load_tif_image_from_url(url):
    response = requests.get(url)
    response.raise_for_status()
    img = tiff.imread(io.BytesIO(response.content))
    img = img.astype(np.float32) / 255.0
    if len(img.shape) == 2:
        img = np.expand_dims(img, axis=-1)
    img = np.expand_dims(img, axis=0)
    return img


@app.route("/predict", methods=["GET"])
def predict():
    year = int(request.args.get("year"))
    month = int(request.args.get("month"))
    lon = float(request.args.get("longitude"))
    lat = float(request.args.get("latitude"))

    now = datetime.now()
    current_year = now.year
    current_month = now.month

    # Gunakan imagery tahun sebelumnya jika future
    imagery_year = year
    if year > current_year:
        imagery_year = current_year
    imagery_year -= 1

    # Ambil citra
    image_url = f"http://suciihtisabi-datafloodsight.hf.space/api/imagery/{imagery_year}?longitude={lon}&latitude={lat}"
    image_response = requests.get(image_url).json()

    if not image_response["success"]:
        return jsonify({"error": "Data citra tidak tersedia"}), 400

    image_download_url = image_response["imagery"]["download_url"]

    # Kurangi bulan untuk API GEE
    api_month = month - 1
    api_year = year
    if api_month <= 0:
        api_month = 12
        api_year -= 1

    # Ambil data tabular
    tabular_url = f"http://suciihtisabi-datafloodsight.hf.space/api/data/{api_year}/{api_month}?longitude={lon}&latitude={lat}"
    tabular_response = requests.get(tabular_url).json()

    if not tabular_response["success"] or len(tabular_response["data"]) == 0:
        return jsonify({"error": "Data tabular tidak ditemukan"}), 400

    tabular_data = tabular_response["data"][0]

    # Data fallback jika masa depan
    fallback_year = current_year - 1
    if year > current_year or (year == current_year and month > current_month):
        # Fallback juga dikurangi sebulan
        fallback_month = month - 1
        fallback_year_adjusted = fallback_year
        if fallback_month <= 0:
            fallback_month = 12
            fallback_year_adjusted -= 1
            
        fallback_url = f"http://suciihtisabi-datafloodsight.hf.space/api/data/{fallback_year_adjusted}/{fallback_month}?longitude={lon}&latitude={lat}"
        fallback_response = requests.get(fallback_url).json()
        if fallback_response["success"] and len(fallback_response["data"]) > 0:
            fallback_data = fallback_response["data"][0]
            for col in ["avg_rainfall", "max_rainfall", "soil_moisture"]:
                tabular_data[col] = fallback_data.get(col, 0.0)

    # Konversi tabular ke dataframe
    tabular_df = pd.DataFrame([tabular_data])
    tabular_df.drop(columns=['NAME_2', 'long', 'lat'], inplace=True)

    # Preprocessing tabular
    try:
        X_tabular = preprocess_tabular_data(tabular_df, preprocessor)
    except Exception as e:
        return jsonify({"error": f"Preprocessing gagal: {str(e)}"}), 500

    # Preprocessing citra
    try:
        image_array = load_image_as_array(image_download_url)
    except Exception as e:
        return jsonify({"error": f"Gagal load citra: {str(e)}"}), 500

    # Prediksi menggunakan signature
    try:
        # Ganti "input_1" dan "input_2" sesuai input signature model Anda
        inputs = {
            "image_input": tf.convert_to_tensor(image_array, dtype=tf.float32),
            "tabular_input": tf.convert_to_tensor(X_tabular, dtype=tf.float32)
        }


        output = infer(**inputs)
        prediction = list(output.values())[0].numpy()
        result = int(np.round(prediction[0][0]))
    except Exception as e:
        return jsonify({"error": f"Prediksi gagal: {str(e)}"}), 500

    return jsonify({
        "success": True,
        "prediction": result,
        "metadata": {
            "district": tabular_response.get("district", "Unknown"),
            "coordinates": {"latitude": lat, "longitude": lon},
            "imagery_year": imagery_year
        }
    })


if __name__ == "__main__":
    port = int(os.environ.get("PORT", 7860))
    app.run(host="0.0.0.0", port=port)