pgzmnk commited on
Commit
d03f5ec
1 Parent(s): 5c10ddc

Fix motherduce.

Browse files
Files changed (1) hide show
  1. app.py +168 -116
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 = 'md_service_token.txt'
25
  # to-do: set-up with papermill parameters
26
- DATE='2020-01-01'
27
  YEAR = 2020
28
- LOCATION=[-74.653370, 5.845328]
29
  ROI_RADIUS = 20000
30
- GEE_SERVICE_ACCOUNT = 'climatebase-july-2023@ee-geospatialml-aquarry.iam.gserviceaccount.com'
31
- GEE_SERVICE_ACCOUNT_CREDENTIALS_FILE = 'ee_service_account.json'
32
- INDICES_FILE = 'indices.yaml'
 
 
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
- def __init__(self,
48
- centroid,
49
- roi_radius,
50
- year,
51
- indices_file,
52
- project_name="",
53
- map = None,
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
- 'collection': collection,
89
- 'percentile': 75,
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, 'r') as stream:
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 'image':
123
- dataset = ee.Image(index_config['gee_path']).clip(self.roi)
124
- if index_config.get('select'):
125
- dataset = dataset.select(index_config['select'])
126
- case 'image_collection':
127
- dataset = ee.ImageCollection(index_config['gee_path']).filterBounds(self.roi).map(lambda image: image.clip(self.roi)).mean()
128
- if index_config.get('select'):
129
- dataset = dataset.select(index_config['select'])
130
- case 'feature_collection':
131
- dataset = ee.Image().float().paint(ee.FeatureCollection(index_config['gee_path']), index_config['select']).clip(self.roi)
132
- case 'algebraic':
133
- image = self._cloudfree(index_config['gee_path'])
134
- dataset = image.normalizedDifference(['B4', 'B3'])
 
 
 
 
 
 
 
 
 
 
 
 
 
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('show'):
141
- map.addLayer(dataset, index_config['viz'], index_config['name'])
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
- 'reducer': ee.Reducer.mean(),
151
- 'geometry': self.roi,
152
- 'scale': 200 # map scale
153
- }).getInfo()
154
- if index_config.get('bandname'):
155
- return out[index_config.get('bandname')]
 
 
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(), # m^2
166
  "geojson": str(roi.getInfo()),
167
- }
168
 
169
- print('data', data)
170
  df = pd.DataFrame(data)
171
  return df
172
 
173
- def set_up_duckdb(service_token_file=None):
174
- print('set up duckdb')
 
175
  # use `climatebase` db
176
- if not os.getenv('motherduck_token');
177
- raise Exception('No motherduck token found. Please set the `motherduck_token` environment variable.')
 
 
178
  else:
179
- con = duckdb.connect('md:climatebase')
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('authenticate_gee')
190
  # to-do: alert if dataset filter date nan
191
- credentials = ee.ServiceAccountCredentials(gee_service_account, gee_service_account_credentials_file)
 
 
192
  ee.Initialize(credentials)
193
-
 
194
  def load_indices(indices_file):
195
  # Read index configurations
196
- with open(indices_file, 'r') as stream:
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(centroid=LOCATION, roi_radius=ROI_RADIUS, year=year, indices_file=INDICES_FILE, project_name=project_name)
 
 
 
 
 
 
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
- # Map = geemap.Map()
 
221
 
 
 
 
 
 
 
222
 
223
- # # Create a cloud-free composite with custom parameters for cloud score threshold and percentile.
224
- # composite_cloudfree = ee.Algorithms.Landsat.simpleComposite(**{
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
- # ig = IndexGenerator(centroid=LOCATION, year=2015, indices_file=INDICES_FILE, project_name='Test Project', map=Map)
235
- # dataset = ig.generate_index(indices['Air'])
 
 
 
 
236
 
237
- # minMax = dataset.clip(roi).reduceRegion(
238
- # geometry = roi,
239
- # reducer = ee.Reducer.minMax(),
240
- # scale= 3000,
241
- # maxPixels= 10e3,
242
- # )
243
 
244
- # minMax.getInfo()
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(f"SELECT COUNT(1) FROM bioindicator WHERE (year = {year} AND project_name = '{project_name}')").fetchall()[0][0]
 
 
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('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)')
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('view_all')
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
- print('Saved records')
 
 
279
 
280
  # preview_table()
281
 
282
- def filter_map(min_price, max_price, boroughs):
283
 
284
- filtered_df = df[(df['neighbourhood_group'].isin(boroughs)) &
285
- (df['price'] > min_price) & (df['price'] < max_price)]
 
 
 
 
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(go.Scattermapbox(
 
290
  customdata=text_list,
291
- lat=filtered_df['latitude'].tolist(),
292
- lon=filtered_df['longitude'].tolist(),
293
- mode='markers',
294
- marker=go.scattermapbox.Marker(
295
- size=6
296
- ),
297
  hoverinfo="text",
298
- hovertemplate='<b>Name</b>: %{customdata[0]}<br><b>Price</b>: $%{customdata[1]}'
299
- ))
 
300
 
301
  fig.update_layout(
302
  mapbox_style="open-street-map",
303
- hovermode='closest',
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(MD_SERVICE_TOKEN)
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='Project Name')
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(calculate_biodiversity_score, inputs=[start_year, end_year, project_name], outputs=results_df)
 
 
 
 
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