RubaAnam1 commited on
Commit
0ee7b3d
·
verified ·
1 Parent(s): 3c62310

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -172
app.py CHANGED
@@ -1,7 +1,6 @@
1
  import streamlit as st
2
  import requests
3
  import os
4
- from urllib.parse import quote
5
 
6
  # =====================================================
7
  # APP
@@ -12,78 +11,29 @@ st.title("🌍 Biodiversity GIS Explorer")
12
  st.write("Explore biodiversity species using GBIF + AI analysis")
13
 
14
  # =====================================================
15
- # GEMINI SAFE
16
- # =====================================================
17
-
18
- def call_gemini(prompt, api_key):
19
-
20
- if not api_key:
21
- return "⚠️ Missing API Key"
22
-
23
- url = (
24
- "https://generativelanguage.googleapis.com/v1beta/models/"
25
- "gemini-3.1-flash-lite:generateContent?key="
26
- f"{api_key}"
27
- )
28
-
29
- payload = {
30
- "contents": [{"parts": [{"text": prompt}]}]
31
- }
32
-
33
- try:
34
- r = requests.post(url, json=payload)
35
- data = r.json()
36
-
37
- if "candidates" not in data:
38
- return f"Gemini Error: {data}"
39
-
40
- return data["candidates"][0]["content"]["parts"][0]["text"]
41
-
42
- except Exception as e:
43
- return f"Gemini Exception: {e}"
44
-
45
-
46
- # =====================================================
47
- # COUNTRY
48
  # =====================================================
49
 
50
  country_codes = {
51
  "sudan": "SD",
52
  "السودان": "SD",
53
  "egypt": "EG",
54
- "مصر": "EG",
55
  "kenya": "KE",
56
- "ethiopia": "ET",
57
- "usa": "US",
58
- "america": "US"
59
  }
60
 
61
  # =====================================================
62
- # FILTERS
63
  # =====================================================
64
 
65
- species_filters = {
66
- "Birds": "class=Aves",
67
- "Plants": "kingdom=Plantae",
68
- "Mammals": "class=Mammalia",
69
- "Reptiles": "class=Reptilia",
70
- "Fish": "class=Actinopterygii",
71
- "Insects": "class=Insecta"
72
- }
73
-
74
- # =====================================================
75
- # CLEAN GBIF (STRONG FILTER ENGINE)
76
- # =====================================================
77
-
78
- def get_species(country_code, filter_value, species_type):
79
 
80
  url = (
81
  "https://api.gbif.org/v1/occurrence/search?"
82
  f"country={country_code}"
83
- f"&{filter_value}"
84
  "&limit=300"
85
- "&occurrence_status=PRESENT"
86
  "&has_coordinate=true"
 
87
  )
88
 
89
  try:
@@ -91,111 +41,66 @@ def get_species(country_code, filter_value, species_type):
91
  data = r.json()
92
  results = data.get("results", [])
93
 
94
- species = []
 
 
 
 
 
 
 
95
 
96
- bad_words = [
97
- "sp.", "cf.", "aff.", "unclassified",
98
- "unknown", "incertae", "sp", "cf"
99
- ]
100
 
101
  for item in results:
102
 
103
  sp = item.get("species")
104
- kingdom = item.get("kingdom")
105
  cls = item.get("class")
106
- status = item.get("establishmentMeans")
107
- tax_status = item.get("taxonomicStatus")
108
 
109
  if not sp:
110
  continue
111
 
112
- sp_low = sp.lower()
113
-
114
- # remove junk names
115
- if any(b in sp_low for b in bad_words):
116
  continue
117
 
118
- # must be proper scientific name
119
  if len(sp.split()) < 2:
120
  continue
121
 
122
- # =================================================
123
- # STRONG FILTER ENGINE
124
- # =================================================
125
-
126
- if tax_status and tax_status != "ACCEPTED":
127
  continue
128
 
129
- # BIRDS ONLY CLEAN
130
- if species_type == "Birds":
131
-
132
- if cls != "Aves":
133
- continue
134
 
135
- if status in ["INTRODUCED", "ASSISTED COLONIZATION", "MANAGED"]:
136
- continue
137
 
138
- # remove urban-only birds (optional but important)
139
- urban = ["Columba livia", "Passer domesticus", "Cairina moschata"]
140
- if sp in urban:
141
- continue
142
 
143
- # REPTILES ONLY CLEAN
144
- elif species_type == "Reptiles":
145
 
146
- if cls != "Reptilia":
147
- continue
148
 
149
- if kingdom != "Animalia":
150
- continue
151
 
152
- # PLANTS
153
- elif species_type == "Plants":
154
- if kingdom != "Plantae":
155
- continue
156
 
157
- # OTHER ANIMALS
158
  else:
159
- if kingdom != "Animalia":
160
- continue
161
-
162
- if sp not in species:
163
- species.append(sp)
164
 
165
- return species[:10]
166
 
167
  except Exception as e:
168
  st.error(f"GBIF Error: {e}")
169
- return []
170
-
171
-
172
- # =====================================================
173
- # LINKS
174
- # =====================================================
175
-
176
- def get_species_links(species_name, country):
177
-
178
- clean = " ".join(species_name.split()[:2])
179
- q = quote(clean)
180
- c = quote(country)
181
-
182
- links = []
183
-
184
- try:
185
- r = requests.get(
186
- f"https://api.gbif.org/v1/species/match?name={q}"
187
- ).json()
188
-
189
- if "usageKey" in r:
190
- links.append(f"- [GBIF](https://www.gbif.org/species/{r['usageKey']})")
191
- except:
192
- pass
193
-
194
- links.append(f"- [Wikipedia](https://en.wikipedia.org/wiki/{clean.replace(' ','_')})")
195
- links.append(f"- [iNaturalist](https://www.inaturalist.org/search?q={q})")
196
- links.append(f"- [Google Scholar](https://scholar.google.com/scholar?q={q}+{c})")
197
-
198
- return links
199
 
200
 
201
  # =====================================================
@@ -204,11 +109,6 @@ def get_species_links(species_name, country):
204
 
205
  country = st.text_input("Enter Country")
206
 
207
- species_type = st.selectbox(
208
- "Select Species Type",
209
- ["Birds", "Plants", "Mammals", "Reptiles", "Fish", "Insects"]
210
- )
211
-
212
  # =====================================================
213
  # RUN
214
  # =====================================================
@@ -221,53 +121,32 @@ if st.button("Search Biodiversity"):
221
  st.error("Country not supported")
222
  st.stop()
223
 
224
- filter_value = species_filters[species_type]
 
225
 
226
- with st.spinner("Fetching clean biodiversity data..."):
227
- species_list = get_species(country_code, filter_value, species_type)
228
-
229
- if not species_list:
230
- st.warning("No clean species found")
231
  st.stop()
232
 
233
- st.subheader("🐾 Species Found")
234
-
235
- for sp in species_list:
236
- st.write("•", sp)
237
-
238
  # =================================================
239
- # AI ANALYSIS
240
  # =================================================
241
 
242
- prompt = f"""
243
- You are a biodiversity scientist.
244
 
245
- Country: {country}
246
- Group: {species_type}
247
 
248
- Species:
249
- {chr(10).join(species_list)}
250
 
251
- Only use verified scientific knowledge. No hallucination.
252
- """
253
-
254
- st.subheader("🤖 AI Analysis")
255
-
256
- st.write(
257
- call_gemini(prompt, os.getenv("GEMINI_API_KEY"))
258
- )
259
 
260
  # =================================================
261
- # LINKS
262
  # =================================================
263
 
264
- st.subheader("🔗 Links")
265
-
266
- for sp in species_list:
267
-
268
- st.markdown(f"### 🔬 {sp}")
269
-
270
- for link in get_species_links(sp, country):
271
- st.markdown(link)
272
 
273
- st.markdown("---")
 
 
1
  import streamlit as st
2
  import requests
3
  import os
 
4
 
5
  # =====================================================
6
  # APP
 
11
  st.write("Explore biodiversity species using GBIF + AI analysis")
12
 
13
  # =====================================================
14
+ # COUNTRY MAP
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  # =====================================================
16
 
17
  country_codes = {
18
  "sudan": "SD",
19
  "السودان": "SD",
20
  "egypt": "EG",
 
21
  "kenya": "KE",
22
+ "ethiopia": "ET"
 
 
23
  }
24
 
25
  # =====================================================
26
+ # GBIF CLEAN FETCH (NO MIXING)
27
  # =====================================================
28
 
29
+ def get_species_grouped(country_code):
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  url = (
32
  "https://api.gbif.org/v1/occurrence/search?"
33
  f"country={country_code}"
 
34
  "&limit=300"
 
35
  "&has_coordinate=true"
36
+ "&occurrence_status=PRESENT"
37
  )
38
 
39
  try:
 
41
  data = r.json()
42
  results = data.get("results", [])
43
 
44
+ grouped = {
45
+ "Birds": [],
46
+ "Reptiles": [],
47
+ "Mammals": [],
48
+ "Insects": [],
49
+ "Amphibians": [],
50
+ "Other": []
51
+ }
52
 
53
+ bad_words = ["sp.", "cf.", "aff.", "unknown", "unclassified"]
 
 
 
54
 
55
  for item in results:
56
 
57
  sp = item.get("species")
 
58
  cls = item.get("class")
59
+ kingdom = item.get("kingdom")
 
60
 
61
  if not sp:
62
  continue
63
 
64
+ if any(b in sp.lower() for b in bad_words):
 
 
 
65
  continue
66
 
 
67
  if len(sp.split()) < 2:
68
  continue
69
 
70
+ # avoid duplicates
71
+ if any(sp in v for v in grouped.values()):
 
 
 
72
  continue
73
 
74
+ # =========================
75
+ # CLASSIFICATION FIX
76
+ # =========================
 
 
77
 
78
+ if kingdom != "Animalia":
79
+ continue
80
 
81
+ if cls == "Aves":
82
+ grouped["Birds"].append(sp)
 
 
83
 
84
+ elif cls == "Reptilia":
85
+ grouped["Reptiles"].append(sp)
86
 
87
+ elif cls == "Mammalia":
88
+ grouped["Mammals"].append(sp)
89
 
90
+ elif cls == "Insecta":
91
+ grouped["Insects"].append(sp)
92
 
93
+ elif cls == "Amphibia":
94
+ grouped["Amphibians"].append(sp)
 
 
95
 
 
96
  else:
97
+ grouped["Other"].append(sp)
 
 
 
 
98
 
99
+ return grouped
100
 
101
  except Exception as e:
102
  st.error(f"GBIF Error: {e}")
103
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
 
106
  # =====================================================
 
109
 
110
  country = st.text_input("Enter Country")
111
 
 
 
 
 
 
112
  # =====================================================
113
  # RUN
114
  # =====================================================
 
121
  st.error("Country not supported")
122
  st.stop()
123
 
124
+ with st.spinner("Fetching biodiversity data..."):
125
+ grouped = get_species_grouped(country_code)
126
 
127
+ if not grouped:
128
+ st.warning("No data found")
 
 
 
129
  st.stop()
130
 
 
 
 
 
 
131
  # =================================================
132
+ # DISPLAY BY GROUP
133
  # =================================================
134
 
135
+ for group_name, species_list in grouped.items():
 
136
 
137
+ if not species_list:
138
+ continue
139
 
140
+ st.subheader(f"🐾 {group_name}")
 
141
 
142
+ for sp in species_list[:10]:
143
+ st.write("•", sp)
 
 
 
 
 
 
144
 
145
  # =================================================
146
+ # SUMMARY
147
  # =================================================
148
 
149
+ st.subheader("📊 Summary")
 
 
 
 
 
 
 
150
 
151
+ for k, v in grouped.items():
152
+ st.write(f"{k}: {len(v)} species")