RubaAnam1 commited on
Commit
ec420b8
·
verified ·
1 Parent(s): 5108b8d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -163
app.py CHANGED
@@ -1,184 +1,99 @@
1
  import streamlit as st
2
  import requests
3
- import os
4
  from urllib.parse import quote
5
 
6
- # =====================================================
7
- # APP
8
- # =====================================================
9
-
10
- st.set_page_config(page_title="Biodiversity GIS Explorer", layout="wide")
11
- st.title("🌍 Biodiversity GIS Explorer")
12
- st.write("Search biodiversity by country and species type")
13
-
14
- # =====================================================
15
- # COUNTRY CODES
16
- # =====================================================
17
-
18
- country_codes = {
19
- "sudan": "SD",
20
- "السودان": "SD",
21
- "egypt": "EG",
22
- "kenya": "KE",
23
- "ethiopia": "ET",
24
- "usa": "US"
25
- }
26
-
27
- # =====================================================
28
- # TYPE FILTERS
29
- # =====================================================
30
-
31
- species_filters = {
32
- "Birds": "class=Aves",
33
- "Reptiles": "class=Reptilia",
34
- "Mammals": "class=Mammalia",
35
- "Insects": "class=Insecta",
36
- "Amphibians": "class=Amphibia",
37
- "Fish": "class=Actinopterygii"
38
- }
39
-
40
- # =====================================================
41
- # LINKS FUNCTION
42
- # =====================================================
43
-
44
- def get_links(species, country):
45
-
46
- q = quote(species)
47
- c = quote(country)
48
-
49
- return [
50
- f"🔗 [GBIF](https://www.gbif.org/species/match?name={q})",
51
- f"📘 [Wikipedia](https://en.wikipedia.org/wiki/{species.replace(' ','_')})",
52
- f"📸 [iNaturalist](https://www.inaturalist.org/search?q={q})",
53
- f"📚 [Google Scholar](https://scholar.google.com/scholar?q={q}+{c})"
54
- ]
55
-
56
- # =====================================================
57
- # GBIF FETCH (FINAL CLEAN FILTER ENGINE)
58
- # =====================================================
59
-
60
- def get_species(country_code, filter_value):
61
-
62
- url = (
63
- "https://api.gbif.org/v1/occurrence/search?"
64
- f"country={country_code}"
65
- f"&{filter_value}"
66
- "&limit=100"
67
- "&has_coordinate=true"
68
- "&occurrence_status=PRESENT"
69
- )
70
-
71
- try:
72
- r = requests.get(url)
73
- data = r.json()
74
- results = data.get("results", [])
75
-
76
- species = []
77
-
78
- bad_words = ["sp.", "cf.", "aff.", "unknown", "unclassified"]
79
-
80
- # 🚫 known invasive / domestic / urban species
81
- blocked_species = [
82
- "Cairina moschata",
83
- "Passer domesticus",
84
- "Columba livia",
85
- "Corvus splendens"
86
- ]
87
-
88
- for item in results:
89
-
90
- sp = item.get("species")
91
- cls = item.get("class")
92
- kingdom = item.get("kingdom")
93
- status = item.get("establishmentMeans")
94
-
95
- if not sp:
96
- continue
97
-
98
- # clean names
99
- if any(b in sp.lower() for b in bad_words):
100
- continue
101
-
102
- if len(sp.split()) < 2:
103
- continue
104
-
105
- # must be animals only
106
- if kingdom != "Animalia":
107
- continue
108
-
109
- # =================================================
110
- # STRONG FILTERING
111
- # =================================================
112
-
113
- # remove invasive / introduced / managed
114
- if status in ["INTRODUCED", "ASSISTED COLONIZATION", "MANAGED"]:
115
- continue
116
-
117
- # remove known bad species
118
- if sp in blocked_species:
119
- continue
120
-
121
- # strict class matching
122
- if filter_value == "class=Aves" and cls != "Aves":
123
- continue
124
- if filter_value == "class=Reptilia" and cls != "Reptilia":
125
- continue
126
- if filter_value == "class=Mammalia" and cls != "Mammalia":
127
- continue
128
- if filter_value == "class=Insecta" and cls != "Insecta":
129
- continue
130
- if filter_value == "class=Amphibia" and cls != "Amphibia":
131
- continue
132
- if filter_value == "class=Actinopterygii" and cls != "Actinopterygii":
133
- continue
134
-
135
- if sp not in species:
136
- species.append(sp)
137
-
138
- return species[:10]
139
-
140
- except Exception as e:
141
- st.error(f"GBIF Error: {e}")
142
- return []
143
-
144
- # =====================================================
145
- # UI
146
- # =====================================================
147
-
148
- country = st.text_input("Enter Country")
149
 
 
150
  species_type = st.selectbox(
151
- "Select Species Type",
152
- ["Birds", "Reptiles", "Mammals", "Insects", "Amphibians", "Fish"]
153
  )
154
 
155
- # =====================================================
156
- # RUN
157
- # =====================================================
158
 
159
- if st.button("Search Biodiversity"):
160
 
161
- country_code = country_codes.get(country.strip().lower())
162
 
163
- if not country_code:
164
- st.error("Country not supported")
165
- st.stop()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
- filter_value = species_filters[species_type]
168
 
169
- species_list = get_species(country_code, filter_value)
 
 
170
 
171
- if not species_list:
172
- st.warning("No clean species found")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  st.stop()
174
 
175
- st.subheader(f"🐾 {species_type} in {country}")
 
 
176
 
177
- for sp in species_list:
178
 
179
- st.markdown(f"### 🔬 {sp}")
180
 
181
- for link in get_links(sp, country):
182
- st.markdown(link)
 
 
183
 
184
  st.markdown("---")
 
1
  import streamlit as st
2
  import requests
 
3
  from urllib.parse import quote
4
 
5
+ st.title("🌍 Biodiversity Explorer (Stable Version)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ country = st.text_input("Country (English only e.g. Sudan)")
8
  species_type = st.selectbox(
9
+ "Type",
10
+ ["Birds", "Reptiles", "Mammals", "Insects", "Fish"]
11
  )
12
 
13
+ # =========================
14
+ # GBIF CLEAN SPECIES SEARCH
15
+ # =========================
16
 
17
+ def get_species(country, group):
18
 
19
+ url = "https://api.gbif.org/v1/species/search"
20
 
21
+ params = {
22
+ "q": group,
23
+ "limit": 10,
24
+ "rank": "SPECIES"
25
+ }
26
+
27
+ r = requests.get(url, params=params)
28
+ data = r.json()
29
+
30
+ results = data.get("results", [])
31
+
32
+ species = []
33
+
34
+ for item in results:
35
+ name = item.get("scientificName")
36
+
37
+ if not name:
38
+ continue
39
+
40
+ # clean junk
41
+ if len(name.split()) < 2:
42
+ continue
43
+
44
+ species.append({
45
+ "name": name,
46
+ "key": item.get("key")
47
+ })
48
+
49
+ return species
50
 
 
51
 
52
+ # =========================
53
+ # SAFE LINKS (NO 404)
54
+ # =========================
55
 
56
+ def links(name, key):
57
+
58
+ q = quote(name)
59
+
60
+ gbif = f"https://www.gbif.org/species/{key}" if key else f"https://www.gbif.org/species/search?q={q}"
61
+
62
+ return {
63
+ "GBIF": gbif,
64
+ "Wikipedia": f"https://en.wikipedia.org/wiki/{name.replace(' ','_')}",
65
+ "iNaturalist": f"https://www.inaturalist.org/search?q={q}",
66
+ "Scholar": f"https://scholar.google.com/scholar?q={q}"
67
+ }
68
+
69
+
70
+ # =========================
71
+ # RUN
72
+ # =========================
73
+
74
+ if st.button("Search"):
75
+
76
+ if not country:
77
+ st.warning("Enter country")
78
+ st.stop()
79
+
80
+ data = get_species(country, species_type)
81
+
82
+ if not data:
83
+ st.warning("No data found")
84
  st.stop()
85
 
86
+ st.subheader(f"{species_type} results")
87
+
88
+ for sp in data:
89
 
90
+ st.markdown(f"### 🔬 {sp['name']}")
91
 
92
+ l = links(sp["name"], sp["key"])
93
 
94
+ st.markdown(f"🔗 [GBIF]({l['GBIF']})")
95
+ st.markdown(f"📘 [Wikipedia]({l['Wikipedia']})")
96
+ st.markdown(f"📸 [iNaturalist]({l['iNaturalist']})")
97
+ st.markdown(f"📚 [Google Scholar]({l['Scholar']})")
98
 
99
  st.markdown("---")