Spaces:
Build error
Build error
pgzmnk
commited on
Commit
•
d03f5ec
1
Parent(s):
5c10ddc
Fix motherduce.
Browse files
app.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import gradio as gr
|
2 |
import plotly.graph_objects as go
|
|
|
3 |
# import ee
|
4 |
# # import geemap
|
5 |
|
@@ -17,22 +18,26 @@ import duckdb
|
|
17 |
import pandas as pd
|
18 |
import datetime
|
19 |
import ee
|
|
|
20 |
# import geemap
|
21 |
import yaml
|
22 |
|
23 |
# Define constants
|
24 |
-
MD_SERVICE_TOKEN =
|
25 |
# to-do: set-up with papermill parameters
|
26 |
-
DATE=
|
27 |
YEAR = 2020
|
28 |
-
LOCATION=[-74.653370, 5.845328]
|
29 |
ROI_RADIUS = 20000
|
30 |
-
GEE_SERVICE_ACCOUNT =
|
31 |
-
|
32 |
-
|
|
|
|
|
33 |
START_YEAR = 2015
|
34 |
END_YEAR = 2022
|
35 |
|
|
|
36 |
class IndexGenerator:
|
37 |
"""
|
38 |
A class to generate indices and compute zonal means.
|
@@ -43,23 +48,25 @@ class IndexGenerator:
|
|
43 |
roi_radius (int, optional): The radius (in meters) for creating a buffer around the centroid as the region of interest. Defaults to 20000.
|
44 |
project_name (str, optional): The name of the project. Defaults to "".
|
45 |
map (geemap.Map, optional): Map object for mapping. Defaults to None (i.e. no map created)
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
|
|
|
|
55 |
self.indices = self._load_indices(indices_file)
|
56 |
self.centroid = centroid
|
57 |
self.roi = ee.Geometry.Point(*centroid).buffer(roi_radius)
|
58 |
self.year = year
|
59 |
self.start_date = str(datetime.date(self.year, 1, 1))
|
60 |
self.end_date = str(datetime.date(self.year, 12, 31))
|
61 |
-
self.daterange=[self.start_date, self.end_date]
|
62 |
-
self.project_name=project_name
|
63 |
self.map = map
|
64 |
if self.map is not None:
|
65 |
self.show = True
|
@@ -84,22 +91,20 @@ class IndexGenerator:
|
|
84 |
)
|
85 |
|
86 |
# Create a cloud-free composite with custom parameters for cloud score threshold and percentile.
|
87 |
-
composite_cloudfree = ee.Algorithms.Landsat.simpleComposite(
|
88 |
-
|
89 |
-
|
90 |
-
'cloudScoreRange': 5
|
91 |
-
})
|
92 |
return composite_cloudfree.clip(self.roi)
|
93 |
|
94 |
def _load_indices(self, indices_file):
|
95 |
# Read index configurations
|
96 |
-
with open(indices_file,
|
97 |
try:
|
98 |
return yaml.safe_load(stream)
|
99 |
except yaml.YAMLError as e:
|
100 |
print(e)
|
101 |
return None
|
102 |
-
|
103 |
def show_map(self, map=None):
|
104 |
if map is not None:
|
105 |
self.map = map
|
@@ -107,7 +112,7 @@ class IndexGenerator:
|
|
107 |
|
108 |
def disable_map(self):
|
109 |
self.show = False
|
110 |
-
|
111 |
def generate_index(self, index_config):
|
112 |
"""
|
113 |
Generates an index based on the provided index configuration.
|
@@ -119,26 +124,39 @@ class IndexGenerator:
|
|
119 |
ee.Image: The generated index clipped to the region of interest.
|
120 |
"""
|
121 |
match index_config["gee_type"]:
|
122 |
-
case
|
123 |
-
dataset = ee.Image(index_config[
|
124 |
-
if index_config.get(
|
125 |
-
dataset = dataset.select(index_config[
|
126 |
-
case
|
127 |
-
dataset =
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
case _:
|
136 |
-
dataset=None
|
137 |
|
138 |
if not dataset:
|
139 |
raise Exception("Failed to generate dataset.")
|
140 |
-
if self.show and index_config.get(
|
141 |
-
map.addLayer(dataset, index_config[
|
142 |
print(f"Generated index: {index_config['name']}")
|
143 |
return dataset
|
144 |
|
@@ -146,176 +164,206 @@ class IndexGenerator:
|
|
146 |
index_config = self.indices[index_key]
|
147 |
dataset = self.generate_index(index_config)
|
148 |
# zm = self._zonal_mean(single, index_config.get('bandname') or 'constant')
|
149 |
-
out = dataset.reduceRegion(
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
|
|
|
|
156 |
return out
|
157 |
|
158 |
def generate_composite_index_df(self, indices=[]):
|
159 |
-
data={
|
160 |
"metric": indices,
|
161 |
-
"year":self.year,
|
162 |
"centroid": str(self.centroid),
|
163 |
"project_name": self.project_name,
|
164 |
"value": list(map(self.zonal_mean_index, indices)),
|
165 |
-
"area": roi.area().getInfo(),
|
166 |
"geojson": str(roi.getInfo()),
|
167 |
-
|
168 |
|
169 |
-
print(
|
170 |
df = pd.DataFrame(data)
|
171 |
return df
|
172 |
|
173 |
-
|
174 |
-
|
|
|
175 |
# use `climatebase` db
|
176 |
-
if not os.getenv(
|
177 |
-
raise Exception(
|
|
|
|
|
178 |
else:
|
179 |
-
con = duckdb.connect(
|
180 |
-
con = duckdb.connect(':climatebase:')
|
181 |
con.sql("USE climatebase;")
|
182 |
|
183 |
# load extensions
|
184 |
con.sql("""INSTALL spatial; LOAD spatial;""")
|
185 |
|
186 |
return con
|
187 |
-
|
|
|
188 |
def authenticate_gee(gee_service_account, gee_service_account_credentials_file):
|
189 |
-
print(
|
190 |
# to-do: alert if dataset filter date nan
|
191 |
-
credentials = ee.ServiceAccountCredentials(
|
|
|
|
|
192 |
ee.Initialize(credentials)
|
193 |
-
|
|
|
194 |
def load_indices(indices_file):
|
195 |
# Read index configurations
|
196 |
-
with open(indices_file,
|
197 |
try:
|
198 |
return yaml.safe_load(stream)
|
199 |
except yaml.YAMLError as e:
|
200 |
print(e)
|
201 |
return None
|
202 |
|
|
|
203 |
def create_dataframe(years, project_name):
|
204 |
-
dfs=[]
|
205 |
print(years)
|
206 |
indices = load_indices(INDICES_FILE)
|
207 |
for year in years:
|
208 |
print(year)
|
209 |
-
ig = IndexGenerator(
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
df = ig.generate_composite_index_df(list(indices.keys()))
|
211 |
dfs.append(df)
|
212 |
return pd.concat(dfs)
|
213 |
|
|
|
214 |
# def preview_table():
|
215 |
# con.sql("FROM bioindicator;").show()
|
216 |
|
217 |
# if __name__ == '__main__':
|
218 |
|
219 |
|
220 |
-
|
|
|
221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
|
223 |
-
|
224 |
-
|
225 |
-
# 'collection': collection,
|
226 |
-
# 'percentile': 75,
|
227 |
-
# 'cloudScoreRange': 5
|
228 |
-
# })
|
229 |
|
230 |
-
# Map.addLayer(composite_cloudfree, {'bands': ['B4', 'B3', 'B2'], 'max': 128}, 'Custom TOA composite')
|
231 |
-
# Map.centerObject(roi, 14)
|
232 |
|
|
|
|
|
233 |
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
|
|
236 |
|
237 |
-
# minMax = dataset.clip(roi).reduceRegion(
|
238 |
-
# geometry = roi,
|
239 |
-
# reducer = ee.Reducer.minMax(),
|
240 |
-
# scale= 3000,
|
241 |
-
# maxPixels= 10e3,
|
242 |
-
# )
|
243 |
|
244 |
-
|
245 |
def calculate_biodiversity_score(start_year, end_year, project_name):
|
246 |
years = []
|
247 |
for year in range(start_year, end_year):
|
248 |
-
row_exists = con.sql(
|
|
|
|
|
249 |
if not row_exists:
|
250 |
years.append(year)
|
251 |
|
252 |
-
if len(years)>0:
|
253 |
df = create_dataframe(years, project_name)
|
254 |
# con.sql('FROM df LIMIT 5').show()
|
255 |
|
256 |
# Write score table to `_temptable`
|
257 |
-
con.sql(
|
258 |
-
|
|
|
259 |
|
260 |
# Create `bioindicator` table IF NOT EXISTS.
|
261 |
-
con.sql(
|
|
|
262 |
USE climatebase;
|
263 |
CREATE TABLE IF NOT EXISTS bioindicator (year BIGINT, project_name VARCHAR(255), value DOUBLE, area DOUBLE, score DOUBLE, CONSTRAINT unique_year_project_name UNIQUE (year, project_name));
|
264 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
265 |
|
266 |
-
return con.sql(f"SELECT * FROM bioindicator WHERE (year > {start_year} AND year <= {end_year} AND project_name = '{project_name}')").df()
|
267 |
|
268 |
def view_all():
|
269 |
-
print(
|
270 |
return con.sql(f"SELECT * FROM bioindicator").df()
|
271 |
|
|
|
272 |
def push_to_md():
|
273 |
# UPSERT project record
|
274 |
-
con.sql(
|
|
|
275 |
INSERT INTO bioindicator FROM _temptable
|
276 |
ON CONFLICT (year, project_name) DO UPDATE SET value = excluded.value;
|
277 |
-
"""
|
278 |
-
|
|
|
|
|
279 |
|
280 |
# preview_table()
|
281 |
|
282 |
-
def filter_map(min_price, max_price, boroughs):
|
283 |
|
284 |
-
|
285 |
-
|
|
|
|
|
|
|
|
|
286 |
names = filtered_df["name"].tolist()
|
287 |
prices = filtered_df["price"].tolist()
|
288 |
text_list = [(names[i], prices[i]) for i in range(0, len(names))]
|
289 |
-
fig = go.Figure(
|
|
|
290 |
customdata=text_list,
|
291 |
-
lat=filtered_df[
|
292 |
-
lon=filtered_df[
|
293 |
-
mode=
|
294 |
-
marker=go.scattermapbox.Marker(
|
295 |
-
size=6
|
296 |
-
),
|
297 |
hoverinfo="text",
|
298 |
-
hovertemplate=
|
299 |
-
)
|
|
|
300 |
|
301 |
fig.update_layout(
|
302 |
mapbox_style="open-street-map",
|
303 |
-
hovermode=
|
304 |
mapbox=dict(
|
305 |
bearing=0,
|
306 |
-
center=go.layout.mapbox.Center(
|
307 |
-
lat=40.67,
|
308 |
-
lon=-73.90
|
309 |
-
),
|
310 |
pitch=0,
|
311 |
-
zoom=9
|
312 |
),
|
313 |
)
|
314 |
|
315 |
return fig
|
316 |
|
|
|
317 |
with gr.Blocks() as demo:
|
318 |
-
con = set_up_duckdb(
|
319 |
authenticate_gee(GEE_SERVICE_ACCOUNT, GEE_SERVICE_ACCOUNT_CREDENTIALS_FILE)
|
320 |
# Create circle buffer over point
|
321 |
# roi = ee.Geometry.Point(*LOCATION).buffer(ROI_RADIUS)
|
@@ -336,7 +384,7 @@ with gr.Blocks() as demo:
|
|
336 |
with gr.Row():
|
337 |
start_year = gr.Number(value=2017, label="Start Year", precision=0)
|
338 |
end_year = gr.Number(value=2022, label="End Year", precision=0)
|
339 |
-
project_name = gr.Textbox(label=
|
340 |
# boroughs = gr.CheckboxGroup(choices=["Queens", "Brooklyn", "Manhattan", "Bronx", "Staten Island"], value=["Queens", "Brooklyn"], label="Select Methodology:")
|
341 |
# btn = gr.Button(value="Update Filter")
|
342 |
with gr.Row():
|
@@ -350,7 +398,11 @@ with gr.Blocks() as demo:
|
|
350 |
)
|
351 |
# demo.load(filter_map, [min_price, max_price, boroughs], map)
|
352 |
# btn.click(filter_map, [min_price, max_price, boroughs], map)
|
353 |
-
calc_btn.click(
|
|
|
|
|
|
|
|
|
354 |
view_btn.click(view_all, outputs=results_df)
|
355 |
save_btn.click(push_to_md)
|
356 |
|
|
|
1 |
import gradio as gr
|
2 |
import plotly.graph_objects as go
|
3 |
+
|
4 |
# import ee
|
5 |
# # import geemap
|
6 |
|
|
|
18 |
import pandas as pd
|
19 |
import datetime
|
20 |
import ee
|
21 |
+
|
22 |
# import geemap
|
23 |
import yaml
|
24 |
|
25 |
# Define constants
|
26 |
+
MD_SERVICE_TOKEN = "md_service_token.txt"
|
27 |
# to-do: set-up with papermill parameters
|
28 |
+
DATE = "2020-01-01"
|
29 |
YEAR = 2020
|
30 |
+
LOCATION = [-74.653370, 5.845328]
|
31 |
ROI_RADIUS = 20000
|
32 |
+
GEE_SERVICE_ACCOUNT = (
|
33 |
+
"climatebase-july-2023@ee-geospatialml-aquarry.iam.gserviceaccount.com"
|
34 |
+
)
|
35 |
+
GEE_SERVICE_ACCOUNT_CREDENTIALS_FILE = "ee_service_account.json"
|
36 |
+
INDICES_FILE = "indices.yaml"
|
37 |
START_YEAR = 2015
|
38 |
END_YEAR = 2022
|
39 |
|
40 |
+
|
41 |
class IndexGenerator:
|
42 |
"""
|
43 |
A class to generate indices and compute zonal means.
|
|
|
48 |
roi_radius (int, optional): The radius (in meters) for creating a buffer around the centroid as the region of interest. Defaults to 20000.
|
49 |
project_name (str, optional): The name of the project. Defaults to "".
|
50 |
map (geemap.Map, optional): Map object for mapping. Defaults to None (i.e. no map created)
|
51 |
+
"""
|
52 |
+
|
53 |
+
def __init__(
|
54 |
+
self,
|
55 |
+
centroid,
|
56 |
+
roi_radius,
|
57 |
+
year,
|
58 |
+
indices_file,
|
59 |
+
project_name="",
|
60 |
+
map=None,
|
61 |
+
):
|
62 |
self.indices = self._load_indices(indices_file)
|
63 |
self.centroid = centroid
|
64 |
self.roi = ee.Geometry.Point(*centroid).buffer(roi_radius)
|
65 |
self.year = year
|
66 |
self.start_date = str(datetime.date(self.year, 1, 1))
|
67 |
self.end_date = str(datetime.date(self.year, 12, 31))
|
68 |
+
self.daterange = [self.start_date, self.end_date]
|
69 |
+
self.project_name = project_name
|
70 |
self.map = map
|
71 |
if self.map is not None:
|
72 |
self.show = True
|
|
|
91 |
)
|
92 |
|
93 |
# Create a cloud-free composite with custom parameters for cloud score threshold and percentile.
|
94 |
+
composite_cloudfree = ee.Algorithms.Landsat.simpleComposite(
|
95 |
+
**{"collection": collection, "percentile": 75, "cloudScoreRange": 5}
|
96 |
+
)
|
|
|
|
|
97 |
return composite_cloudfree.clip(self.roi)
|
98 |
|
99 |
def _load_indices(self, indices_file):
|
100 |
# Read index configurations
|
101 |
+
with open(indices_file, "r") as stream:
|
102 |
try:
|
103 |
return yaml.safe_load(stream)
|
104 |
except yaml.YAMLError as e:
|
105 |
print(e)
|
106 |
return None
|
107 |
+
|
108 |
def show_map(self, map=None):
|
109 |
if map is not None:
|
110 |
self.map = map
|
|
|
112 |
|
113 |
def disable_map(self):
|
114 |
self.show = False
|
115 |
+
|
116 |
def generate_index(self, index_config):
|
117 |
"""
|
118 |
Generates an index based on the provided index configuration.
|
|
|
124 |
ee.Image: The generated index clipped to the region of interest.
|
125 |
"""
|
126 |
match index_config["gee_type"]:
|
127 |
+
case "image":
|
128 |
+
dataset = ee.Image(index_config["gee_path"]).clip(self.roi)
|
129 |
+
if index_config.get("select"):
|
130 |
+
dataset = dataset.select(index_config["select"])
|
131 |
+
case "image_collection":
|
132 |
+
dataset = (
|
133 |
+
ee.ImageCollection(index_config["gee_path"])
|
134 |
+
.filterBounds(self.roi)
|
135 |
+
.map(lambda image: image.clip(self.roi))
|
136 |
+
.mean()
|
137 |
+
)
|
138 |
+
if index_config.get("select"):
|
139 |
+
dataset = dataset.select(index_config["select"])
|
140 |
+
case "feature_collection":
|
141 |
+
dataset = (
|
142 |
+
ee.Image()
|
143 |
+
.float()
|
144 |
+
.paint(
|
145 |
+
ee.FeatureCollection(index_config["gee_path"]),
|
146 |
+
index_config["select"],
|
147 |
+
)
|
148 |
+
.clip(self.roi)
|
149 |
+
)
|
150 |
+
case "algebraic":
|
151 |
+
image = self._cloudfree(index_config["gee_path"])
|
152 |
+
dataset = image.normalizedDifference(["B4", "B3"])
|
153 |
case _:
|
154 |
+
dataset = None
|
155 |
|
156 |
if not dataset:
|
157 |
raise Exception("Failed to generate dataset.")
|
158 |
+
if self.show and index_config.get("show"):
|
159 |
+
map.addLayer(dataset, index_config["viz"], index_config["name"])
|
160 |
print(f"Generated index: {index_config['name']}")
|
161 |
return dataset
|
162 |
|
|
|
164 |
index_config = self.indices[index_key]
|
165 |
dataset = self.generate_index(index_config)
|
166 |
# zm = self._zonal_mean(single, index_config.get('bandname') or 'constant')
|
167 |
+
out = dataset.reduceRegion(
|
168 |
+
**{
|
169 |
+
"reducer": ee.Reducer.mean(),
|
170 |
+
"geometry": self.roi,
|
171 |
+
"scale": 200, # map scale
|
172 |
+
}
|
173 |
+
).getInfo()
|
174 |
+
if index_config.get("bandname"):
|
175 |
+
return out[index_config.get("bandname")]
|
176 |
return out
|
177 |
|
178 |
def generate_composite_index_df(self, indices=[]):
|
179 |
+
data = {
|
180 |
"metric": indices,
|
181 |
+
"year": self.year,
|
182 |
"centroid": str(self.centroid),
|
183 |
"project_name": self.project_name,
|
184 |
"value": list(map(self.zonal_mean_index, indices)),
|
185 |
+
"area": roi.area().getInfo(), # m^2
|
186 |
"geojson": str(roi.getInfo()),
|
187 |
+
}
|
188 |
|
189 |
+
print("data", data)
|
190 |
df = pd.DataFrame(data)
|
191 |
return df
|
192 |
|
193 |
+
|
194 |
+
def set_up_duckdb():
|
195 |
+
print("set up duckdb")
|
196 |
# use `climatebase` db
|
197 |
+
if not os.getenv("motherduck_token"):
|
198 |
+
raise Exception(
|
199 |
+
"No motherduck token found. Please set the `motherduck_token` environment variable."
|
200 |
+
)
|
201 |
else:
|
202 |
+
con = duckdb.connect("md:climatebase")
|
|
|
203 |
con.sql("USE climatebase;")
|
204 |
|
205 |
# load extensions
|
206 |
con.sql("""INSTALL spatial; LOAD spatial;""")
|
207 |
|
208 |
return con
|
209 |
+
|
210 |
+
|
211 |
def authenticate_gee(gee_service_account, gee_service_account_credentials_file):
|
212 |
+
print("authenticate_gee")
|
213 |
# to-do: alert if dataset filter date nan
|
214 |
+
credentials = ee.ServiceAccountCredentials(
|
215 |
+
gee_service_account, gee_service_account_credentials_file
|
216 |
+
)
|
217 |
ee.Initialize(credentials)
|
218 |
+
|
219 |
+
|
220 |
def load_indices(indices_file):
|
221 |
# Read index configurations
|
222 |
+
with open(indices_file, "r") as stream:
|
223 |
try:
|
224 |
return yaml.safe_load(stream)
|
225 |
except yaml.YAMLError as e:
|
226 |
print(e)
|
227 |
return None
|
228 |
|
229 |
+
|
230 |
def create_dataframe(years, project_name):
|
231 |
+
dfs = []
|
232 |
print(years)
|
233 |
indices = load_indices(INDICES_FILE)
|
234 |
for year in years:
|
235 |
print(year)
|
236 |
+
ig = IndexGenerator(
|
237 |
+
centroid=LOCATION,
|
238 |
+
roi_radius=ROI_RADIUS,
|
239 |
+
year=year,
|
240 |
+
indices_file=INDICES_FILE,
|
241 |
+
project_name=project_name,
|
242 |
+
)
|
243 |
df = ig.generate_composite_index_df(list(indices.keys()))
|
244 |
dfs.append(df)
|
245 |
return pd.concat(dfs)
|
246 |
|
247 |
+
|
248 |
# def preview_table():
|
249 |
# con.sql("FROM bioindicator;").show()
|
250 |
|
251 |
# if __name__ == '__main__':
|
252 |
|
253 |
|
254 |
+
# Map = geemap.Map()
|
255 |
+
|
256 |
|
257 |
+
# # Create a cloud-free composite with custom parameters for cloud score threshold and percentile.
|
258 |
+
# composite_cloudfree = ee.Algorithms.Landsat.simpleComposite(**{
|
259 |
+
# 'collection': collection,
|
260 |
+
# 'percentile': 75,
|
261 |
+
# 'cloudScoreRange': 5
|
262 |
+
# })
|
263 |
|
264 |
+
# Map.addLayer(composite_cloudfree, {'bands': ['B4', 'B3', 'B2'], 'max': 128}, 'Custom TOA composite')
|
265 |
+
# Map.centerObject(roi, 14)
|
|
|
|
|
|
|
|
|
266 |
|
|
|
|
|
267 |
|
268 |
+
# ig = IndexGenerator(centroid=LOCATION, year=2015, indices_file=INDICES_FILE, project_name='Test Project', map=Map)
|
269 |
+
# dataset = ig.generate_index(indices['Air'])
|
270 |
|
271 |
+
# minMax = dataset.clip(roi).reduceRegion(
|
272 |
+
# geometry = roi,
|
273 |
+
# reducer = ee.Reducer.minMax(),
|
274 |
+
# scale= 3000,
|
275 |
+
# maxPixels= 10e3,
|
276 |
+
# )
|
277 |
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
|
279 |
+
# minMax.getInfo()
|
280 |
def calculate_biodiversity_score(start_year, end_year, project_name):
|
281 |
years = []
|
282 |
for year in range(start_year, end_year):
|
283 |
+
row_exists = con.sql(
|
284 |
+
f"SELECT COUNT(1) FROM bioindicator WHERE (year = {year} AND project_name = '{project_name}')"
|
285 |
+
).fetchall()[0][0]
|
286 |
if not row_exists:
|
287 |
years.append(year)
|
288 |
|
289 |
+
if len(years) > 0:
|
290 |
df = create_dataframe(years, project_name)
|
291 |
# con.sql('FROM df LIMIT 5').show()
|
292 |
|
293 |
# Write score table to `_temptable`
|
294 |
+
con.sql(
|
295 |
+
"CREATE OR REPLACE TABLE _temptable AS SELECT *, (value * area) AS score FROM (SELECT year, project_name, AVG(value) AS value, area FROM df GROUP BY year, project_name, area ORDER BY project_name)"
|
296 |
+
)
|
297 |
|
298 |
# Create `bioindicator` table IF NOT EXISTS.
|
299 |
+
con.sql(
|
300 |
+
"""
|
301 |
USE climatebase;
|
302 |
CREATE TABLE IF NOT EXISTS bioindicator (year BIGINT, project_name VARCHAR(255), value DOUBLE, area DOUBLE, score DOUBLE, CONSTRAINT unique_year_project_name UNIQUE (year, project_name));
|
303 |
+
"""
|
304 |
+
)
|
305 |
+
|
306 |
+
return con.sql(
|
307 |
+
f"SELECT * FROM bioindicator WHERE (year > {start_year} AND year <= {end_year} AND project_name = '{project_name}')"
|
308 |
+
).df()
|
309 |
|
|
|
310 |
|
311 |
def view_all():
|
312 |
+
print("view_all")
|
313 |
return con.sql(f"SELECT * FROM bioindicator").df()
|
314 |
|
315 |
+
|
316 |
def push_to_md():
|
317 |
# UPSERT project record
|
318 |
+
con.sql(
|
319 |
+
"""
|
320 |
INSERT INTO bioindicator FROM _temptable
|
321 |
ON CONFLICT (year, project_name) DO UPDATE SET value = excluded.value;
|
322 |
+
"""
|
323 |
+
)
|
324 |
+
print("Saved records")
|
325 |
+
|
326 |
|
327 |
# preview_table()
|
328 |
|
|
|
329 |
|
330 |
+
def filter_map(min_price, max_price, boroughs):
|
331 |
+
filtered_df = df[
|
332 |
+
(df["neighbourhood_group"].isin(boroughs))
|
333 |
+
& (df["price"] > min_price)
|
334 |
+
& (df["price"] < max_price)
|
335 |
+
]
|
336 |
names = filtered_df["name"].tolist()
|
337 |
prices = filtered_df["price"].tolist()
|
338 |
text_list = [(names[i], prices[i]) for i in range(0, len(names))]
|
339 |
+
fig = go.Figure(
|
340 |
+
go.Scattermapbox(
|
341 |
customdata=text_list,
|
342 |
+
lat=filtered_df["latitude"].tolist(),
|
343 |
+
lon=filtered_df["longitude"].tolist(),
|
344 |
+
mode="markers",
|
345 |
+
marker=go.scattermapbox.Marker(size=6),
|
|
|
|
|
346 |
hoverinfo="text",
|
347 |
+
hovertemplate="<b>Name</b>: %{customdata[0]}<br><b>Price</b>: $%{customdata[1]}",
|
348 |
+
)
|
349 |
+
)
|
350 |
|
351 |
fig.update_layout(
|
352 |
mapbox_style="open-street-map",
|
353 |
+
hovermode="closest",
|
354 |
mapbox=dict(
|
355 |
bearing=0,
|
356 |
+
center=go.layout.mapbox.Center(lat=40.67, lon=-73.90),
|
|
|
|
|
|
|
357 |
pitch=0,
|
358 |
+
zoom=9,
|
359 |
),
|
360 |
)
|
361 |
|
362 |
return fig
|
363 |
|
364 |
+
|
365 |
with gr.Blocks() as demo:
|
366 |
+
con = set_up_duckdb()
|
367 |
authenticate_gee(GEE_SERVICE_ACCOUNT, GEE_SERVICE_ACCOUNT_CREDENTIALS_FILE)
|
368 |
# Create circle buffer over point
|
369 |
# roi = ee.Geometry.Point(*LOCATION).buffer(ROI_RADIUS)
|
|
|
384 |
with gr.Row():
|
385 |
start_year = gr.Number(value=2017, label="Start Year", precision=0)
|
386 |
end_year = gr.Number(value=2022, label="End Year", precision=0)
|
387 |
+
project_name = gr.Textbox(label="Project Name")
|
388 |
# boroughs = gr.CheckboxGroup(choices=["Queens", "Brooklyn", "Manhattan", "Bronx", "Staten Island"], value=["Queens", "Brooklyn"], label="Select Methodology:")
|
389 |
# btn = gr.Button(value="Update Filter")
|
390 |
with gr.Row():
|
|
|
398 |
)
|
399 |
# demo.load(filter_map, [min_price, max_price, boroughs], map)
|
400 |
# btn.click(filter_map, [min_price, max_price, boroughs], map)
|
401 |
+
calc_btn.click(
|
402 |
+
calculate_biodiversity_score,
|
403 |
+
inputs=[start_year, end_year, project_name],
|
404 |
+
outputs=results_df,
|
405 |
+
)
|
406 |
view_btn.click(view_all, outputs=results_df)
|
407 |
save_btn.click(push_to_md)
|
408 |
|