Wall06 commited on
Commit
599bdb1
·
verified ·
1 Parent(s): 1a1e0c3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -55
app.py CHANGED
@@ -10,7 +10,7 @@ from PIL import Image
10
  import qrcode
11
  from fpdf import FPDF
12
  from io import BytesIO
13
- from sentinelhub import SHConfig, MimeType, CRS, BBox, SentinelHubRequest, DataCollection
14
  from groq import Groq
15
 
16
  # -------------------- ENVIRONMENT VARIABLES --------------------
@@ -21,9 +21,11 @@ SENTINEL_CLIENT_ID = os.getenv("SENTINEL_CLIENT_ID")
21
  SENTINEL_CLIENT_SECRET = os.getenv("SENTINEL_CLIENT_SECRET")
22
 
23
  # -------------------- SENTINEL HUB CONFIG --------------------
 
24
  config = SHConfig()
25
- config.client_id = SENTINEL_CLIENT_ID
26
- config.client_secret = SENTINEL_CLIENT_SECRET
 
27
 
28
  # -------------------- AI SUMMARY FUNCTIONS --------------------
29
  def hf_summary(text):
@@ -37,17 +39,20 @@ def hf_summary(text):
37
 
38
  def groq_summary(text):
39
  try:
 
40
  client = Groq(api_key=GROQ_API_KEY)
41
  completion = client.chat.completions.create(
42
  model="mixtral-8x7b-32768",
43
  messages=[{"role": "user", "content": text}]
44
  )
45
- return completion.choices[0].message["content"]
46
- except:
 
47
  return None
48
 
49
  def deepseek_summary(text):
50
  try:
 
51
  url = "https://api.deepseek.com/v1/chat/completions"
52
  headers = {
53
  "Authorization": f"Bearer {DEEPSEEK_API_KEY}",
@@ -63,6 +68,7 @@ def deepseek_summary(text):
63
  return None
64
 
65
  def smart_summary(text):
 
66
  if GROQ_API_KEY:
67
  out = groq_summary(text)
68
  if out: return out
@@ -72,7 +78,7 @@ def smart_summary(text):
72
  if HF_API_KEY:
73
  out = hf_summary(text)
74
  if out: return out
75
- return "⚠ No AI model available. Check API keys."
76
 
77
  # -------------------- WATER QUALITY CALCULATIONS --------------------
78
  def calculate_wqi(pH, do, nutrients):
@@ -98,6 +104,8 @@ def river_stability(wqi, hsi, erosion):
98
 
99
  # -------------------- SATELLITE IMAGE ANALYSIS --------------------
100
  def analyze_satellite_image(img):
 
 
101
  img_array = np.array(img.convert("L"))
102
  turbidity_score = int(np.mean(img_array)/2.55) # scale 0-100
103
  return turbidity_score
@@ -128,23 +136,42 @@ def generate_pdf(wqi, hsi, erosion, turbidity, summary_text):
128
  pdf.cell(0,10,f"Turbidity: {turbidity}", ln=True)
129
  pdf.ln(10)
130
 
131
- # AI Summary + Biodiversity / Mitigation
132
- pdf.multi_cell(0, 8, summary_text)
 
 
133
 
134
  # QR code
135
  qr = qrcode.QRCode(box_size=4)
136
- qr.add_data("FlumenIntel")
137
  qr.make(fit=True)
138
  img = qr.make_image(fill_color="black", back_color="white")
 
 
139
  qr_buffer = BytesIO()
140
  img.save(qr_buffer, format="PNG")
141
  qr_buffer.seek(0)
142
- pdf.image(qr_buffer, x=80, y=pdf.get_y(), w=50)
143
 
144
- output = BytesIO()
145
- pdf.output(output)
146
- output.seek(0)
147
- return output
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
  # -------------------- MAIN FUNCTION --------------------
150
  def predict_river(flow_rate, water_temp, sediment, construction, pH, do, nutrients, sat_img):
@@ -157,50 +184,43 @@ def predict_river(flow_rate, water_temp, sediment, construction, pH, do, nutrien
157
  stability = river_stability(wqi, hsi, erosion)
158
  potability = potability_status(wqi)
159
 
160
- # AI Summary Input for full report
161
  summary_input = f"""
162
- Hydrological Data:
163
- - Flow rate: {flow_rate} m³/s
164
- - Water temperature: {water_temp} °C
165
- - Sediment: {sediment}
166
- - Construction: {construction}
167
-
168
- Chemical Data:
169
- - pH: {pH}
170
- - Dissolved Oxygen: {do} mg/L
171
- - Nutrient Load: {nutrients}
172
-
173
- Satellite Analysis:
174
- - Turbidity Score: {turbidity}
175
-
176
- Derived Scores:
177
- - WQI: {wqi}
178
- - HSI: {hsi}
179
- - Erosion: {erosion}
180
- - Potability: {potability}
181
- - Stability: {stability}
182
-
183
- Generate a **comprehensive environmental report** that includes:
184
- 1. River health summary
185
- 2. Potential impact on biodiversity and fish
186
- 3. Recommended mitigation measures with explanation
187
- 4. Suggested monitoring frequency
188
- """
189
  summary = smart_summary(summary_input)
190
 
191
  # Plot
192
  fig = create_plots(wqi, hsi, erosion, turbidity)
193
 
194
- # PDF
195
- pdf_file = generate_pdf(wqi, hsi, erosion, turbidity, summary)
196
 
197
- return f"River Stability: {stability}/100\nPotability: {potability}", fig, pdf_file, summary
 
 
 
 
 
 
198
  except Exception as e:
199
- return f"Error: {str(e)}", None, None, None
 
200
 
201
  # -------------------- GRADIO UI --------------------
202
- with gr.Blocks(title="FlumenIntel - River Health Predictor") as demo:
203
- gr.Markdown("<h1 style='text-align:center;color:#1E90FF'>FlumenIntel 🌊</h1>", elem_id="title")
 
 
 
 
 
204
  with gr.Row():
205
  with gr.Column():
206
  flow_rate = gr.Number(label="Flow Rate (m³/s)", value=50)
@@ -210,11 +230,13 @@ with gr.Blocks(title="FlumenIntel - River Health Predictor") as demo:
210
  pH = gr.Number(label="pH Level", value=7)
211
  do = gr.Number(label="Dissolved Oxygen (mg/L)", value=8)
212
  nutrients = gr.Number(label="Nutrient Load (N+P)", value=3)
213
- sat_img = gr.Image(label="Satellite Image (Upload or URL)", type="pil")
214
- predict_btn = gr.Button("Predict River Health")
 
215
  with gr.Column():
216
  result_text = gr.Textbox(label="Predicted Output", interactive=False)
217
  plot_output = gr.Plot(label="River Health Metrics")
 
218
  pdf_output = gr.File(label="Download PDF Report")
219
  ai_summary = gr.Textbox(label="AI Environmental Summary", interactive=False)
220
 
@@ -224,8 +246,5 @@ with gr.Blocks(title="FlumenIntel - River Health Predictor") as demo:
224
  outputs=[result_text, plot_output, pdf_output, ai_summary]
225
  )
226
 
227
- # -------------------- CUSTOM CSS --------------------
228
- custom_css = """
229
- #title {background: linear-gradient(90deg, #1E90FF, #00CED1); padding: 20px; border-radius: 15px; color:white;}
230
- """
231
- demo.launch(share=True, css=custom_css)
 
10
  import qrcode
11
  from fpdf import FPDF
12
  from io import BytesIO
13
+ from sentinelhub import SHConfig, SentinelHubRequest
14
  from groq import Groq
15
 
16
  # -------------------- ENVIRONMENT VARIABLES --------------------
 
21
  SENTINEL_CLIENT_SECRET = os.getenv("SENTINEL_CLIENT_SECRET")
22
 
23
  # -------------------- SENTINEL HUB CONFIG --------------------
24
+ # Only configure if keys are present to avoid startup crashes
25
  config = SHConfig()
26
+ if SENTINEL_CLIENT_ID and SENTINEL_CLIENT_SECRET:
27
+ config.client_id = SENTINEL_CLIENT_ID
28
+ config.client_secret = SENTINEL_CLIENT_SECRET
29
 
30
  # -------------------- AI SUMMARY FUNCTIONS --------------------
31
  def hf_summary(text):
 
39
 
40
  def groq_summary(text):
41
  try:
42
+ if not GROQ_API_KEY: return None
43
  client = Groq(api_key=GROQ_API_KEY)
44
  completion = client.chat.completions.create(
45
  model="mixtral-8x7b-32768",
46
  messages=[{"role": "user", "content": text}]
47
  )
48
+ return completion.choices[0].message.content
49
+ except Exception as e:
50
+ print(f"Groq Error: {e}")
51
  return None
52
 
53
  def deepseek_summary(text):
54
  try:
55
+ if not DEEPSEEK_API_KEY: return None
56
  url = "https://api.deepseek.com/v1/chat/completions"
57
  headers = {
58
  "Authorization": f"Bearer {DEEPSEEK_API_KEY}",
 
68
  return None
69
 
70
  def smart_summary(text):
71
+ # Try Groq first (fastest/best for this), then DeepSeek, then HF
72
  if GROQ_API_KEY:
73
  out = groq_summary(text)
74
  if out: return out
 
78
  if HF_API_KEY:
79
  out = hf_summary(text)
80
  if out: return out
81
+ return "⚠ No AI model available. Please check API keys in Settings."
82
 
83
  # -------------------- WATER QUALITY CALCULATIONS --------------------
84
  def calculate_wqi(pH, do, nutrients):
 
104
 
105
  # -------------------- SATELLITE IMAGE ANALYSIS --------------------
106
  def analyze_satellite_image(img):
107
+ if img is None:
108
+ return 0
109
  img_array = np.array(img.convert("L"))
110
  turbidity_score = int(np.mean(img_array)/2.55) # scale 0-100
111
  return turbidity_score
 
136
  pdf.cell(0,10,f"Turbidity: {turbidity}", ln=True)
137
  pdf.ln(10)
138
 
139
+ # AI Summary
140
+ # Handle encoding for PDF
141
+ safe_summary = summary_text.encode('latin-1', 'replace').decode('latin-1')
142
+ pdf.multi_cell(0, 8, safe_summary)
143
 
144
  # QR code
145
  qr = qrcode.QRCode(box_size=4)
146
+ qr.add_data("FlumenIntel Project")
147
  qr.make(fit=True)
148
  img = qr.make_image(fill_color="black", back_color="white")
149
+
150
+ # Save QR to buffer
151
  qr_buffer = BytesIO()
152
  img.save(qr_buffer, format="PNG")
153
  qr_buffer.seek(0)
 
154
 
155
+ # Embed QR in PDF
156
+ # Note: FPDF image handling with streams requires a temp file in some versions,
157
+ # but let's try direct stream if supported, or save temp.
158
+ # Safe method for basic FPDF:
159
+ import tempfile
160
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp:
161
+ img.save(tmp.name)
162
+ pdf.image(tmp.name, x=150, y=10, w=30)
163
+
164
+ # Output PDF to bytes
165
+ # FPDF output returns a string in older versions, we convert to bytes
166
+ try:
167
+ pdf_bytes = pdf.output(dest='S').encode('latin-1')
168
+ except:
169
+ # Fallback for newer FPDF versions if installed
170
+ pdf_bytes = pdf.output(dest='S')
171
+
172
+ output_buffer = BytesIO(pdf_bytes)
173
+ output_buffer.seek(0)
174
+ return output_buffer.getvalue() # Return bytes directly for Gradio
175
 
176
  # -------------------- MAIN FUNCTION --------------------
177
  def predict_river(flow_rate, water_temp, sediment, construction, pH, do, nutrients, sat_img):
 
184
  stability = river_stability(wqi, hsi, erosion)
185
  potability = potability_status(wqi)
186
 
187
+ # AI Summary Input
188
  summary_input = f"""
189
+ River Analysis Data:
190
+ - WQI: {wqi} ({potability})
191
+ - Flow: {flow_rate} m3/s
192
+ - Erosion Risk: {erosion}
193
+ - Turbidity: {turbidity}
194
+
195
+ Task: Write a short technical summary recommending specific mitigation for this river.
196
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  summary = smart_summary(summary_input)
198
 
199
  # Plot
200
  fig = create_plots(wqi, hsi, erosion, turbidity)
201
 
202
+ # PDF (Generate a temporary file path for Gradio to download)
203
+ pdf_bytes = generate_pdf(wqi, hsi, erosion, turbidity, summary)
204
 
205
+ # Save to a temp file for Gradio to serve
206
+ import tempfile
207
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_pdf:
208
+ tmp_pdf.write(pdf_bytes)
209
+ pdf_path = tmp_pdf.name
210
+
211
+ return f"River Stability: {stability}/100\nPotability: {potability}", fig, pdf_path, summary
212
  except Exception as e:
213
+ import traceback
214
+ return f"Error: {str(e)}\n{traceback.format_exc()}", None, None, None
215
 
216
  # -------------------- GRADIO UI --------------------
217
+ custom_css = """
218
+ #title {background: linear-gradient(90deg, #1E90FF, #00CED1); padding: 20px; border-radius: 15px; color: white; text-align: center;}
219
+ """
220
+
221
+ with gr.Blocks(title="FlumenIntel", css=custom_css) as demo:
222
+ gr.Markdown("<h1 id='title'>FlumenIntel 🌊</h1>")
223
+
224
  with gr.Row():
225
  with gr.Column():
226
  flow_rate = gr.Number(label="Flow Rate (m³/s)", value=50)
 
230
  pH = gr.Number(label="pH Level", value=7)
231
  do = gr.Number(label="Dissolved Oxygen (mg/L)", value=8)
232
  nutrients = gr.Number(label="Nutrient Load (N+P)", value=3)
233
+ sat_img = gr.Image(label="Satellite Image", type="pil")
234
+ predict_btn = gr.Button("Predict River Health", variant="primary")
235
+
236
  with gr.Column():
237
  result_text = gr.Textbox(label="Predicted Output", interactive=False)
238
  plot_output = gr.Plot(label="River Health Metrics")
239
+ # PDF output must be type="filepath" for downloading
240
  pdf_output = gr.File(label="Download PDF Report")
241
  ai_summary = gr.Textbox(label="AI Environmental Summary", interactive=False)
242
 
 
246
  outputs=[result_text, plot_output, pdf_output, ai_summary]
247
  )
248
 
249
+ if __name__ == "__main__":
250
+ demo.launch()