cassiebuhler commited on
Commit
e1041f5
·
1 Parent(s): 73b7b64

WIP. App uses new data; need to work on prompt

Browse files
Files changed (4) hide show
  1. app/app.py +38 -33
  2. app/system_prompt.txt +53 -33
  3. app/utils.py +24 -96
  4. app/variables.py +82 -51
app/app.py CHANGED
@@ -35,14 +35,14 @@ current_tables = con.list_tables()
35
  if "mydata" not in set(current_tables):
36
  tbl = con.read_parquet(ca_parquet)
37
  con.create_table("mydata", tbl)
 
38
  ca = con.table("mydata")
39
 
40
-
41
  for key in [
42
  'richness', 'rsr', 'irrecoverable_carbon', 'manageable_carbon',
43
  'fire', 'rxburn', 'disadvantaged_communities',
44
- 'svi'
45
- ]:
46
  if key not in st.session_state:
47
  st.session_state[key] = False
48
 
@@ -161,12 +161,13 @@ llm = ChatOpenAI(model="gpt-4", temperature=0)
161
 
162
  managers = ca.sql("SELECT DISTINCT manager FROM mydata;").execute()
163
  names = ca.sql("SELECT name FROM mydata GROUP BY name HAVING SUM(acres) >10000;").execute()
 
164
 
165
  from langchain_core.prompts import ChatPromptTemplate
166
  prompt = ChatPromptTemplate.from_messages([
167
  ("system", template),
168
  ("human", "{input}")
169
- ]).partial(dialect="duckdb", table_info = ca.schema(), managers = managers, names = names)
170
 
171
  structured_llm = llm.with_structured_output(SQLResponse)
172
  few_shot_structured_llm = prompt | structured_llm
@@ -328,21 +329,21 @@ with st.sidebar:
328
  m.add_cog_layer(url_man_carbon, palette="purples", name="Manageable Carbon", opacity = a_climate, fit_bounds=False)
329
 
330
 
331
- # Justice40 Section
332
- with st.expander("🌱 Climate & Economic Justice"):
333
- a_justice = st.slider("transparency", 0.0, 1.0, 0.07, key = "social justice")
334
- show_justice40 = st.toggle("Disadvantaged Communities (Justice40)", key = "disadvantaged_communities", value=chatbot_toggles['disadvantaged_communities'])
335
-
336
- if show_justice40:
337
- m.add_pmtiles(url_justice40, style=justice40_style, name="Justice40", opacity=a_justice, tooltip=False, fit_bounds = False)
338
 
339
- # SVI Section
340
- with st.expander("🏡 Social Vulnerability"):
341
- a_svi = st.slider("transparency", 0.0, 1.0, 0.1, key = "SVI")
 
342
  show_sv = st.toggle("Social Vulnerability Index (SVI)", key = "svi", value=chatbot_toggles['svi'])
343
-
 
 
 
344
  if show_sv:
345
- m.add_pmtiles(url_svi, style = get_sv_style("RPL_THEMES"), opacity=a_svi, tooltip=False, fit_bounds = False)
346
 
347
  # Fire Section
348
  with st.expander("🔥 Fire"):
@@ -353,10 +354,10 @@ with st.sidebar:
353
 
354
 
355
  if show_fire_10:
356
- m.add_pmtiles(url_calfire, style=fire_style("layer2"), name="CALFIRE Fire Polygons (2013-2023)", opacity=a_fire, tooltip=False, fit_bounds = True)
357
 
358
  if show_rx_10:
359
- m.add_pmtiles(url_rxburn, style=rx_style("layer2"), name="CAL FIRE Prescribed Burns (2013-2023)", opacity=a_fire, tooltip=False, fit_bounds = True)
360
 
361
 
362
  st.divider()
@@ -388,17 +389,21 @@ with st.sidebar:
388
  if 'out' not in locals():
389
  style = get_pmtiles_style(style_options[color_choice], alpha, filter_cols, filter_vals)
390
  legend_d = {cat: color for cat, color in style_options[color_choice]['stops']}
 
 
 
 
 
391
  m.add_legend(legend_dict = legend_d, position = 'bottom-left')
392
  m.add_pmtiles(ca_pmtiles, style=style, name="CA", opacity=alpha, tooltip=True, fit_bounds = True)
393
 
394
 
395
-
396
  column = select_column[color_choice]
397
 
398
  select_colors = {
399
  "Year": year["stops"],
400
  "GAP Code": gap["stops"],
401
- "Status": status["stops"],
402
  "Ecoregion": ecoregion["stops"],
403
  "Manager Type": manager["stops"],
404
  "Easement": easement["stops"],
@@ -423,14 +428,14 @@ total_percent = df.percent_protected.sum().round(2)
423
 
424
 
425
  # charts displayed based on color_by variable
426
- richness_chart = bar_chart(df, column, 'mean_richness', "Species Richness")
427
- rsr_chart = bar_chart(df, column, 'mean_rsr', "Range-Size Rarity")
428
- irr_carbon_chart = bar_chart(df, column, 'mean_irrecoverable_carbon', "Irrecoverable Carbon")
429
- man_carbon_chart = bar_chart(df, column, 'mean_manageable_carbon', "Manageable Carbon")
430
  fire_10_chart = bar_chart(df, column, 'mean_fire', "Fires (2013-2023)")
431
  rx_10_chart = bar_chart(df, column, 'mean_rxburn',"Prescribed Burns (2013-2023)")
432
- justice40_chart = bar_chart(df, column, 'mean_disadvantaged_communities', "Disadvantaged Communities (Justice40) ")
433
- svi_chart = bar_chart(df, column, 'mean_svi', "Social Vulnerability Index (2023)")
434
 
435
 
436
  main = st.container()
@@ -441,7 +446,7 @@ with main:
441
  with map_col:
442
  m.to_streamlit(height=650)
443
  if 'out' not in locals():
444
- st.dataframe(df_tab, use_container_width = True)
445
  else:
446
  st.dataframe(out, use_container_width = True)
447
 
@@ -463,18 +468,18 @@ with main:
463
  if show_manageable_carbon:
464
  st.altair_chart(man_carbon_chart, use_container_width=True)
465
 
466
- if show_fire_10:
467
- st.altair_chart(fire_10_chart, use_container_width=True)
468
-
469
- if show_rx_10:
470
- st.altair_chart(rx_10_chart, use_container_width=True)
471
-
472
  if show_justice40:
473
  st.altair_chart(justice40_chart, use_container_width=True)
474
 
475
  if show_sv:
476
  st.altair_chart(svi_chart, use_container_width=True)
 
 
 
477
 
 
 
 
478
 
479
 
480
 
 
35
  if "mydata" not in set(current_tables):
36
  tbl = con.read_parquet(ca_parquet)
37
  con.create_table("mydata", tbl)
38
+
39
  ca = con.table("mydata")
40
 
41
+
42
  for key in [
43
  'richness', 'rsr', 'irrecoverable_carbon', 'manageable_carbon',
44
  'fire', 'rxburn', 'disadvantaged_communities',
45
+ 'svi']:
 
46
  if key not in st.session_state:
47
  st.session_state[key] = False
48
 
 
161
 
162
  managers = ca.sql("SELECT DISTINCT manager FROM mydata;").execute()
163
  names = ca.sql("SELECT name FROM mydata GROUP BY name HAVING SUM(acres) >10000;").execute()
164
+ ecoregions = ca.sql("SELECT DISTINCT ecoregion FROM mydata;").execute()
165
 
166
  from langchain_core.prompts import ChatPromptTemplate
167
  prompt = ChatPromptTemplate.from_messages([
168
  ("system", template),
169
  ("human", "{input}")
170
+ ]).partial(dialect="duckdb", table_info = ca.schema(), managers = managers, names = names, ecoregions = ecoregions)
171
 
172
  structured_llm = llm.with_structured_output(SQLResponse)
173
  few_shot_structured_llm = prompt | structured_llm
 
329
  m.add_cog_layer(url_man_carbon, palette="purples", name="Manageable Carbon", opacity = a_climate, fit_bounds=False)
330
 
331
 
332
+ # # Justice40 Section
333
+ # with st.expander("🌱 Climate & Economic Justice"):
334
+ # a_justice = st.slider("transparency", 0.0, 1.0, 0.07, key = "social justice")
 
 
 
 
335
 
336
+ # People Section
337
+ with st.expander("🏡 People"):
338
+ a_people = st.slider("transparency", 0.0, 1.0, 0.1, key = "SVI")
339
+ show_justice40 = st.toggle("Disadvantaged Communities (Justice40)", key = "disadvantaged_communities", value=chatbot_toggles['disadvantaged_communities'])
340
  show_sv = st.toggle("Social Vulnerability Index (SVI)", key = "svi", value=chatbot_toggles['svi'])
341
+
342
+ if show_justice40:
343
+ m.add_pmtiles(url_justice40, style=justice40_style, name="Justice40", opacity=a_people, tooltip=False, fit_bounds = False)
344
+
345
  if show_sv:
346
+ m.add_pmtiles(url_svi, style = svi_style, opacity=a_people, tooltip=False, fit_bounds = False)
347
 
348
  # Fire Section
349
  with st.expander("🔥 Fire"):
 
354
 
355
 
356
  if show_fire_10:
357
+ m.add_pmtiles(url_calfire, style=fire_style, name="CALFIRE Fire Polygons (2013-2023)", opacity=a_fire, tooltip=False, fit_bounds = False)
358
 
359
  if show_rx_10:
360
+ m.add_pmtiles(url_rxburn, style=rx_style, name="CAL FIRE Prescribed Burns (2013-2023)", opacity=a_fire, tooltip=False, fit_bounds = False)
361
 
362
 
363
  st.divider()
 
389
  if 'out' not in locals():
390
  style = get_pmtiles_style(style_options[color_choice], alpha, filter_cols, filter_vals)
391
  legend_d = {cat: color for cat, color in style_options[color_choice]['stops']}
392
+
393
+ # shorten legend for ecoregions
394
+ if color_choice == "Ecoregion":
395
+ legend_d = {key.replace("California", "CA"): value for key, value in legend_d.items()}
396
+
397
  m.add_legend(legend_dict = legend_d, position = 'bottom-left')
398
  m.add_pmtiles(ca_pmtiles, style=style, name="CA", opacity=alpha, tooltip=True, fit_bounds = True)
399
 
400
 
 
401
  column = select_column[color_choice]
402
 
403
  select_colors = {
404
  "Year": year["stops"],
405
  "GAP Code": gap["stops"],
406
+ "30x30 Status": status["stops"],
407
  "Ecoregion": ecoregion["stops"],
408
  "Manager Type": manager["stops"],
409
  "Easement": easement["stops"],
 
428
 
429
 
430
  # charts displayed based on color_by variable
431
+ richness_chart = bar_chart(df, column, 'mean_richness', "Species Richness (2022)")
432
+ rsr_chart = bar_chart(df, column, 'mean_rsr', "Range-Size Rarity (2022)")
433
+ irr_carbon_chart = bar_chart(df, column, 'mean_irrecoverable_carbon', "Irrecoverable Carbon (2018)")
434
+ man_carbon_chart = bar_chart(df, column, 'mean_manageable_carbon', "Manageable Carbon (2018)")
435
  fire_10_chart = bar_chart(df, column, 'mean_fire', "Fires (2013-2023)")
436
  rx_10_chart = bar_chart(df, column, 'mean_rxburn',"Prescribed Burns (2013-2023)")
437
+ justice40_chart = bar_chart(df, column, 'mean_disadvantaged', "Disadvantaged Communities (2020)")
438
+ svi_chart = bar_chart(df, column, 'mean_svi', "Social Vulnerability Index (2022)")
439
 
440
 
441
  main = st.container()
 
446
  with map_col:
447
  m.to_streamlit(height=650)
448
  if 'out' not in locals():
449
+ st.dataframe(df_tab, use_container_width = True)
450
  else:
451
  st.dataframe(out, use_container_width = True)
452
 
 
468
  if show_manageable_carbon:
469
  st.altair_chart(man_carbon_chart, use_container_width=True)
470
 
 
 
 
 
 
 
471
  if show_justice40:
472
  st.altair_chart(justice40_chart, use_container_width=True)
473
 
474
  if show_sv:
475
  st.altair_chart(svi_chart, use_container_width=True)
476
+
477
+ if show_fire_10:
478
+ st.altair_chart(fire_10_chart, use_container_width=True)
479
 
480
+ if show_rx_10:
481
+ st.altair_chart(rx_10_chart, use_container_width=True)
482
+
483
 
484
 
485
 
app/system_prompt.txt CHANGED
@@ -11,10 +11,12 @@ Ensure the response contains only this JSON object, with no additional text, for
11
  # Important Details
12
 
13
  - For map-related queries (e.g., "show me"), ALWAYS include "id," "geom", "name," and "acres" in the results, PLUS any other columns referenced in the query (e.g., in conditions, calculations, or subqueries). This output structure is MANDATORY for all map-related queries.
 
14
  - ONLY use LIMIT in your SQL queries if the user specifies a quantity (e.g., 'show me 5'). Otherwise, return all matching data without a limit.
15
  - Wrap each column name in double quotes (") to denote them as delimited identifiers.
16
  - Pay attention to use only the column names you can see in the tables below. DO NOT query for columns that do not exist.
17
- If the query mentions "biodiversity" without specifying a column, default to using "richness" (species richness). Explain this choice and that they can also request "rsr" (range-size rarity).
 
18
  - If the query mentions carbon without specifying a column, use "irrecoverable carbon". Explain this choice and list the other carbon-related columns they can ask for, along with their definitions.
19
  - If the query asks about the manager, use the "manager" column. You MUST ALWAYS explain the difference between manager and manager_type in your response. Clarify that "manager" refers to the name of the managing entity (e.g., an agency), while "manager_type" specifies the type of jurisdiction (e.g., Federal, State, Non Profit). Also, let the user know they can include "manager_type" in their query if they want to refine their results.
20
  - If the user's query is unclear, DO NOT make assumptions. Instead, ask for clarification and provide examples of similar queries you can handle, using the columns or data available. You MUST ONLY deliver accurate results.
@@ -22,6 +24,38 @@ Ensure the response contains only this JSON object, with no additional text, for
22
  - Users may not be familiar with this data, so your explanation should be short, clear, and easily understandable. You MUST state which column(s) you used to gather their query, along with definition(s) of the column(s). Do NOT explain SQL commands.
23
  - If the prompt is unrelated to the California dataset, provide examples of relevant queries that you can answer.
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  # Example Questions and How to Approach Them
26
 
27
  ## Example:
@@ -36,9 +70,9 @@ example_assistant: {{"sql_query":
36
  ## Example:
37
  example_user: "Which gap code has been impacted the most by fire?"
38
  example_assistant: {{"sql_query":
39
- SELECT "reGAP", SUM("fire") AS temp
40
  FROM mydata
41
- GROUP BY "reGAP"
42
  ORDER BY temp ASC
43
  LIMIT 1;
44
  "explanation":"I used the `fire` column, which shows the percentage of each area burned over the past 10 years (2013–2022), summing it for each GAP code to find the one with the highest total fire impact."
@@ -49,12 +83,13 @@ example_user: "Who manages the land with the worst biodiversity and highest SVI?
49
  example_assistant: {{"sql_query":
50
  SELECT manager,richness, svi
51
  FROM mydata
 
52
  GROUP BY "manager"
53
  ORDER BY richness ASC, svi DESC
54
  LIMIT 1;
55
  "explanation": "I identified the land manager with the worst biodiversity and highest Social Vulnerability Index (SVI) by analyzing the columns: `richness`, which measures species richness, and `svi`, which represents social vulnerability based on factors like socioeconomic status, household characteristics, racial & ethnic minority status, and housing & transportation.
56
 
57
- I sorted the data by richness in ascending order (worst biodiversity first) and svi in descending order (highest vulnerability). The result provides the manager, which is the name of the entity managing the land. Note that the manager column refers to the specific agency or organization responsible for managing the land, while`manager_type` categorizes the type of jurisdiction (e.g., Federal, State, Non Profit)."
58
  }}
59
 
60
 
@@ -63,6 +98,7 @@ example_user: "Show me the biggest protected area"
63
  example_assistant: {{"sql_query":
64
  SELECT "id", "geom", "name", "acres", "manager", "manager_type", "acres"
65
  FROM mydata
 
66
  ORDER BY "acres" DESC
67
  LIMIT 1;
68
  "explanation": "I identified the biggest protected area by sorting the data in descending order based on the `acres` column, which represents the size of each area."
@@ -72,6 +108,7 @@ example_user: "Show me the 50 most biodiverse areas found in disadvantaged commu
72
  example_assistant: {{"sql_query":
73
  SELECT "id", "geom", "name", "acres", "richness", "disadvantaged_communities" FROM mydata
74
  WHERE "disadvantaged_communities" > 0
 
75
  ORDER BY "richness" DESC
76
  LIMIT 50;
77
  "explanation": "I used the `richness` column to measure biodiversity and the `disadvantaged_communities` column to identify areas located in disadvantaged communities. The `disadvantaged_communities` value is derived from the Justice40 initiative, which identifies communities burdened by systemic inequities and vulnerabilities across multiple domains, including climate resilience, energy access, health disparities, housing affordability, pollution exposure, transportation infrastructure, water quality, and workforce opportunities.
@@ -87,9 +124,9 @@ sql_query:
87
  SELECT PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY "richness") AS temp
88
  FROM mydata
89
  )
90
- SELECT "id", "geom", "name", "acres","richness", "reGAP"
91
  FROM mydata
92
- WHERE "reGAP" = 3
93
  AND "fire" >= 0.5
94
  and "manager_type" = "Federal"
95
  AND "richness" > (SELECT temp FROM temp_tab);
@@ -102,34 +139,17 @@ sql_query:
102
  FROM mydata
103
  WHERE "easement" = "True";
104
 
105
-
106
- # Detailed Explanation of the Columns in the California Dataset
107
- - "established": The time range which the land was acquired, either "2024" or "pre-2024".
108
- - "reGAP": The GAP code; corresponds to the level of protection the area has. There are 4 gap codes and are defined as the following.
109
- GAP 1: Permanently protected to maintain a natural state, allowing natural disturbances or mimicking them through management.
110
- GAP 2: Permanently protected but may allow some uses or management practices that degrade natural communities or suppress natural disturbances.
111
- GAP 3: Permanently protected from major land cover conversion but allows some extractive uses (e.g., logging, mining) and protects federally listed species.
112
- GAP 4: No protection mandates; land may be converted to unnatural habitat types or its management intent is unknown.
113
- - "name": The name of a protected area. The user may use a shortened name and/or not capitalize it. For example, "redwoods" may refer to "Redwood National Park", or "klamath" refers to "Klamath National Forest". Another example, "san diego wildlife refuge" could refer to multiple areas, so you would use "WHERE LOWER("name") LIKE '%san diego%' AND LOWER("name") LIKE '%wildlife%' AND LOWER("name") LIKE '%refuge%';" in your SQL query, to ensure that it is case-insensitive and matches any record that includes our phrases, because we don't want to overlook a match. If the name isn't capitalized, you MUST ensure the search is case-insensitive by converting "name" to lowercase.
114
- The names of the largest parks are {names}.
115
- - "access_type": Level of access to the land: "Unknown Access","Restricted Access","No Public Access" and "Open Access".
116
- - "manager": The name of land manager for the area. Also referred to as the agency name. These are the manager names: {managers}. Users might use acronyms or could omit "United States" in the agency name, make sure to use the name used in the table. Some examples: "BLM" or "Bureau of Land Management" refers to the "United States Bureau of Land Management" or "CDFW" is "California Department of Fish and Wildlife". Similar to the "name" field, you can search for managers using "LIKE" in the SQL query.
117
- - "manager_type": The jurisdiction of the land manager: "Federal","State","Non Profit","Special District","Unknown","County","City","Joint","Tribal","Private","HOA". If the user says "non-profit", do not use a hyphen in your query.
118
- - "easement": Boolean value; whether or not the land is an easement.
119
- - "acres": Land acreage; measures the size of the area.
120
- - "id": unique id for each area. This is necessary for displaying queried results on a map.
121
- - "type": Physical type of area, either "Land" or "Water".
122
- - "richness": Species richness; higher values indicate better biodiversity.
123
- - "rsr": Range-size rarity; higher values indicate better rarity metrics.
124
- - "svi": Social Vulnerability Index based on 4 themes: 1) socioeconomic status (e.g. poverty, unemployment, housing cost burden, education, and health insurance), 2) household characteristics (e.g. age, disability, single-parent households, and language proficiency), 3) racial & ethnic minority status (e.g. race and ethnicity variables), and 4) housing & transportation (housing type, crowding, vehicles, and group quarters.). Higher values indicate greater vulnerability.
125
- - "disadvantaged_communities": Justice40-defined disadvantaged communities overburdened by climate, energy, health, housing, pollution, transportation, water, and workforce factors. Higher values indicate more disadvantage. Range is between 0 and 1.
126
- - "fire": The percentage of the area burned by fires from (2013-2022). Areas can burn more than once, thus the percentage can be above 1
127
- - "rxburn": The percentage of the area affected by prescribed burns from (2013-2022). Areas can be burned more than once.
128
- - "status": The conservation status. GAP 1 and 2 count towards 30x30, thus are "30x30-conserved", GAP 3 and 4 land are grouped into "other-conserved", and areas outside of GAP are designed "non-conserved".
129
- - "ecoregion": Ecoregions are areas with similar ecosystems and environmental resources. The ecoregions in California are: 'Sierra Nevada Foothills','Southern Cascades','Southeastern Great Basin','Southern CA Mountains and Valleys','Sonoran Desert', 'Northwestern Basin','Colorado Desert','Central Valley Coast Ranges', 'Great Valley (South)', 'Sierra Nevada','Northern CA Coast Ranges', 'Northern CA Interior Coast Ranges','Mojave Desert', 'Mono', 'Southern CA Coast', 'Modoc Plateau', 'Klamath Mountains','Northern CA Coast','Great Valley (North)', 'Central CA Coast', and 'None'.
130
 
131
 
132
- Only use the following tables:
133
- {table_info}.
134
 
135
  Question: {input}
 
11
  # Important Details
12
 
13
  - For map-related queries (e.g., "show me"), ALWAYS include "id," "geom", "name," and "acres" in the results, PLUS any other columns referenced in the query (e.g., in conditions, calculations, or subqueries). This output structure is MANDATORY for all map-related queries.
14
+ - Unless the user species to include land without a GAP code, do NOT include land where "status" is "non-conserved" in your SQL queries.
15
  - ONLY use LIMIT in your SQL queries if the user specifies a quantity (e.g., 'show me 5'). Otherwise, return all matching data without a limit.
16
  - Wrap each column name in double quotes (") to denote them as delimited identifiers.
17
  - Pay attention to use only the column names you can see in the tables below. DO NOT query for columns that do not exist.
18
+ - ONLY WRITE SQL QUERIES BASED ON THE SCHEMA AND METADATA PROVIDED. DO NOT QUERY RECORDS THAT DON'T EXIST.
19
+ - If the query mentions "biodiversity" without specifying a column, default to using "richness" (species richness). Explain this choice and that they can also request "rsr" (range-size rarity).
20
  - If the query mentions carbon without specifying a column, use "irrecoverable carbon". Explain this choice and list the other carbon-related columns they can ask for, along with their definitions.
21
  - If the query asks about the manager, use the "manager" column. You MUST ALWAYS explain the difference between manager and manager_type in your response. Clarify that "manager" refers to the name of the managing entity (e.g., an agency), while "manager_type" specifies the type of jurisdiction (e.g., Federal, State, Non Profit). Also, let the user know they can include "manager_type" in their query if they want to refine their results.
22
  - If the user's query is unclear, DO NOT make assumptions. Instead, ask for clarification and provide examples of similar queries you can handle, using the columns or data available. You MUST ONLY deliver accurate results.
 
24
  - Users may not be familiar with this data, so your explanation should be short, clear, and easily understandable. You MUST state which column(s) you used to gather their query, along with definition(s) of the column(s). Do NOT explain SQL commands.
25
  - If the prompt is unrelated to the California dataset, provide examples of relevant queries that you can answer.
26
 
27
+
28
+ # Detailed Explanation of the Columns in the California Dataset
29
+ - "established": The time range which the land was acquired, either "2024" or "pre-2024".
30
+ - "gap_code": The GAP code; corresponds to the level of protection the area has. There are 4 gap codes and are defined as the following.
31
+ GAP 1: Permanently protected to maintain a natural state, allowing natural disturbances or mimicking them through management.
32
+ GAP 2: Permanently protected but may allow some uses or management practices that degrade natural communities or suppress natural disturbances.
33
+ GAP 3: Permanently protected from major land cover conversion but allows some extractive uses (e.g., logging, mining) and protects federally listed species.
34
+ GAP 4: No protection mandates; land may be converted to unnatural habitat types or its management intent is unknown.
35
+ - "name": The name of a protected area. The user may use a shortened name and/or not capitalize it. For example, "redwoods" may refer to "Redwood National Park", or "klamath" refers to "Klamath National Forest". Another example, "san diego wildlife refuge" could refer to multiple areas, so you would use "WHERE LOWER("name") LIKE '%san diego%' AND LOWER("name") LIKE '%wildlife%' AND LOWER("name") LIKE '%refuge%';" in your SQL query, to ensure that it is case-insensitive and matches any record that includes our phrases, because we don't want to overlook a match. If the name isn't capitalized, you MUST ensure the search is case-insensitive by converting "name" to lowercase.
36
+ The names of the largest parks are {names}.
37
+ - "access_type": Level of access to the land: "Unknown Access","Restricted Access","No Public Access" and "Open Access".
38
+ - "manager": The name of land manager for the area. Also referred to as the agency name. These are the manager names: {managers}. Users might use acronyms or could omit "United States" in the agency name, make sure to use the name used in the table. Some examples: "BLM" or "Bureau of Land Management" refers to the "United States Bureau of Land Management" or "CDFW" is "California Department of Fish and Wildlife". Similar to the "name" field, you can search for managers using "LIKE" in the SQL query.
39
+ - "manager_type": The jurisdiction of the land manager: "Federal","State","Non Profit","Special District","Unknown","County","City","Joint","Tribal","Private","HOA". If the user says "non-profit", do not use a hyphen in your query.
40
+ - "easement": Boolean value; whether or not the land is an easement.
41
+ - "acres": Land acreage; measures the size of the area.
42
+ - "id": unique id for each area. This is necessary for displaying queried results on a map.
43
+ - "type": Physical type of area, either "Land" or "Water".
44
+ - "richness": Species richness; higher values indicate better biodiversity.
45
+ - "rsr": Range-size rarity; higher values indicate better rarity metrics.
46
+ - "svi": Social Vulnerability Index based on 4 themes: socioeconomic status, household characteristics, racial & ethnic minority status, and housing & transportation. Higher values indicate greater vulnerability.
47
+ - "disadvantaged_communities": Justice40-defined disadvantaged communities overburdened by climate, energy, health, housing, pollution, transportation, water, and workforce factors. Higher values indicate more disadvantage. Range is between 0 and 1.
48
+ - "fire": The percentage of the area burned by fires from (2013-2022). Areas can burn more than once, thus the percentage can be above 1
49
+ - "rxburn": The percentage of the area affected by prescribed burns from (2013-2022). Areas can be burned more than once.
50
+ - "status": The conservation status. GAP 1 and 2 count towards 30x30, thus are "30x30-conserved", GAP 3 and 4 land are grouped into "other-conserved", and areas outside of GAP are designed "non-conserved". By default, do NOT include 'non-conserved' areas in calculations, unless the users specifically requests it.
51
+ - "ecoregion": Ecoregions are areas with similar ecosystems and environmental resources. The ONLY ecoregions you have access to are: {ecoregions}. Users may shorten the ecoregions. For example, "Southern CA Mountains" would refer to "Southern California Mountains and Valleys".
52
+
53
+
54
+
55
+ Only use the following table:
56
+ {table_info}.
57
+
58
+
59
  # Example Questions and How to Approach Them
60
 
61
  ## Example:
 
70
  ## Example:
71
  example_user: "Which gap code has been impacted the most by fire?"
72
  example_assistant: {{"sql_query":
73
+ SELECT "gap_code", SUM("fire") AS temp
74
  FROM mydata
75
+ GROUP BY "gap_code"
76
  ORDER BY temp ASC
77
  LIMIT 1;
78
  "explanation":"I used the `fire` column, which shows the percentage of each area burned over the past 10 years (2013–2022), summing it for each GAP code to find the one with the highest total fire impact."
 
83
  example_assistant: {{"sql_query":
84
  SELECT manager,richness, svi
85
  FROM mydata
86
+ WHERE "status" != 'non-conserved'
87
  GROUP BY "manager"
88
  ORDER BY richness ASC, svi DESC
89
  LIMIT 1;
90
  "explanation": "I identified the land manager with the worst biodiversity and highest Social Vulnerability Index (SVI) by analyzing the columns: `richness`, which measures species richness, and `svi`, which represents social vulnerability based on factors like socioeconomic status, household characteristics, racial & ethnic minority status, and housing & transportation.
91
 
92
+ I sorted the data by richness in ascending order (worst biodiversity first) and svi in descending order (highest vulnerability). The result provides the manager, which is the name of the entity managing the land. Note that the manager column refers to the specific agency or organization responsible for managing the land, while `manager_type` categorizes the type of jurisdiction (e.g., Federal, State, Non Profit)."
93
  }}
94
 
95
 
 
98
  example_assistant: {{"sql_query":
99
  SELECT "id", "geom", "name", "acres", "manager", "manager_type", "acres"
100
  FROM mydata
101
+ WHERE "status" != 'non-conserved'
102
  ORDER BY "acres" DESC
103
  LIMIT 1;
104
  "explanation": "I identified the biggest protected area by sorting the data in descending order based on the `acres` column, which represents the size of each area."
 
108
  example_assistant: {{"sql_query":
109
  SELECT "id", "geom", "name", "acres", "richness", "disadvantaged_communities" FROM mydata
110
  WHERE "disadvantaged_communities" > 0
111
+ WHERE "status" != 'non-conserved'
112
  ORDER BY "richness" DESC
113
  LIMIT 50;
114
  "explanation": "I used the `richness` column to measure biodiversity and the `disadvantaged_communities` column to identify areas located in disadvantaged communities. The `disadvantaged_communities` value is derived from the Justice40 initiative, which identifies communities burdened by systemic inequities and vulnerabilities across multiple domains, including climate resilience, energy access, health disparities, housing affordability, pollution exposure, transportation infrastructure, water quality, and workforce opportunities.
 
124
  SELECT PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY "richness") AS temp
125
  FROM mydata
126
  )
127
+ SELECT "id", "geom", "name", "acres", "richness", "gap_code"
128
  FROM mydata
129
+ WHERE "gap_code" = 3
130
  AND "fire" >= 0.5
131
  and "manager_type" = "Federal"
132
  AND "richness" > (SELECT temp FROM temp_tab);
 
139
  FROM mydata
140
  WHERE "easement" = "True";
141
 
142
+ ## Example:
143
+ example_user: "Which ecoregions are in the top 10% of range-size rarity?"
144
+ sql_query:
145
+ WITH temp_tab AS (
146
+ SELECT PERCENTILE_CONT(0.90) WITHIN GROUP (ORDER BY "rsr") AS temp
147
+ FROM mydata
148
+ )
149
+ SELECT "ecoregion"
150
+ FROM mydata
151
+ WHERE "rsr" > (SELECT temp FROM temp_tab);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
 
 
 
154
 
155
  Question: {input}
app/utils.py CHANGED
@@ -28,7 +28,7 @@ def get_summary(ca, combined_filter, column, colors=None): #summary stats, based
28
  mean_manageable_carbon = (_.manageable_carbon * _.acres).sum() / _.acres.sum(),
29
  mean_fire = (_.fire *_.acres).sum()/_.acres.sum(),
30
  mean_rxburn = (_.rxburn *_.acres).sum()/_.acres.sum(),
31
- mean_disadvantaged_communities = (_.disadvantaged_communities * _.acres).sum() / _.acres.sum(),
32
  mean_svi = (_.svi * _.acres).sum() / _.acres.sum(),
33
  )
34
  .mutate(percent_protected=_.percent_protected.round(1))
@@ -52,8 +52,10 @@ def summary_table(ca, column, colors, filter_cols, filter_vals,colorby_vals): #
52
  filter_cols.append(column)
53
  filters.append(getattr(_, column).isin(colorby_vals[column]))
54
  combined_filter = reduce(lambda x, y: x & y, filters) #combining all the filters into ibis filter expression
55
- if column == "status":
 
56
  combined_filter = (combined_filter) | (_.status.isin(['30x30-conserved','other-conserved','non-conserved']))
 
57
  df = get_summary(ca, combined_filter, [column], colors) # df used for charts
58
  df_tab = get_summary(ca, combined_filter, filter_cols, colors = None) #df used for printed table
59
  return df, df_tab
@@ -65,7 +67,7 @@ def area_plot(df, column): #percent protected pie chart
65
  alt.Theta("percent_protected:Q").stack(True),
66
  )
67
  pie = ( base
68
- .mark_arc(innerRadius= 40, outerRadius=100)
69
  .encode(alt.Color("color:N").scale(None).legend(None),
70
  tooltip=['percent_protected', column])
71
  )
@@ -78,14 +80,13 @@ def area_plot(df, column): #percent protected pie chart
78
 
79
 
80
  def bar_chart(df, x, y, title): #display summary stats for color_by column
81
-
82
  #axis label angles / chart size
83
- if x in ["manager_type", 'ecoregion','status']: #labels are too long, making vertical
84
  angle = 270
85
  height = 373
86
- if x == 'ecoregion':
87
- height = 430
88
-
89
  else: #other labels are horizontal
90
  angle = 0
91
  height = 310
@@ -100,28 +101,26 @@ def bar_chart(df, x, y, title): #display summary stats for color_by column
100
  else:
101
  sort = 'x'
102
 
 
 
 
 
 
 
 
103
  x_title = next(key for key, value in select_column.items() if value == x)
104
- chart = alt.Chart(df).mark_bar().transform_calculate(
105
- access_label=f"replace(datum.{x}, ' Access', '')" #omit access from access_type labels so it fits in frame
106
  ).encode(
107
- x=alt.X("access_label:N",
108
  axis=alt.Axis(labelAngle=angle, title=x_title, labelLimit = 200),
109
  sort=sort),
110
  y=alt.Y(y, axis=alt.Axis()),
111
- color=alt.Color('color').scale(None)
112
- ).properties(width="container", height=height, title = title
113
- )
114
- # sizing for poster
115
- # ).configure_title(
116
- # fontSize=40
117
- # ).configure_axis(
118
- # labelFontSize=24,
119
- # titleFontSize=34
120
- # )
121
  return chart
122
 
123
 
124
-
125
  def getButtons(style_options, style_choice, default_gap=None): #finding the buttons selected to use as filters
126
  column = style_options[style_choice]['property']
127
  opts = [style[0] for style in style_options[style_choice]['stops']]
@@ -136,7 +135,6 @@ def getButtons(style_options, style_choice, default_gap=None): #finding the butt
136
  return d
137
 
138
 
139
-
140
  def getColorVals(style_options, style_choice):
141
  #df_tab only includes filters selected, we need to manually add "color_by" column (if it's not already a filter).
142
  column = style_options[style_choice]['property']
@@ -146,81 +144,11 @@ def getColorVals(style_options, style_choice):
146
  return d
147
 
148
 
149
-
150
- def fire_style(layer):
151
- return {"version": 8,
152
- "sources": {
153
- "source1": {
154
- "type": "vector",
155
- "url": "pmtiles://" + url_calfire,
156
- "attribution": "CAL FIRE"
157
- }
158
- },
159
- "layers": [
160
- {
161
- "id": "fire",
162
- "source": "source1",
163
- "source-layer": layer,
164
- "type": "fill",
165
- "paint": {
166
- "fill-color": "#D22B2B",
167
- }
168
- }
169
- ]
170
- }
171
- def rx_style(layer):
172
- return{
173
- "version": 8,
174
- "sources": {
175
- "source2": {
176
- "type": "vector",
177
- "url": "pmtiles://" + url_rxburn,
178
- "attribution": "CAL FIRE"
179
- }
180
- },
181
- "layers": [
182
- {
183
- "id": "fire",
184
- "source": "source2",
185
- "source-layer": layer,
186
- # "filter": [">=", ["get", "YEAR_"], year],
187
- "type": "fill",
188
- "paint": {
189
- "fill-color": "#702963",
190
- }
191
- }
192
- ]
193
- }
194
-
195
- def get_sv_style(column):
196
- return {
197
- "layers": [
198
- {
199
- "id": "SVI",
200
- "source": column, #need different "source" for multiple pmtiles layers w/ same file
201
- "source-layer": "SVI2020_US_county",
202
- "filter": ["match", ["get", "STATE"], "California", True, False],
203
- "type": "fill",
204
- "paint": {
205
- "fill-color": [
206
- "interpolate", ["linear"], ["get", column],
207
- 0, white,
208
- 1, svi_color
209
- ]
210
- }
211
- }
212
- ]
213
- }
214
-
215
-
216
  def get_pmtiles_style(paint, alpha, filter_cols, filter_vals):
217
  filters = []
218
  for col, val in zip(filter_cols, filter_vals):
219
  filters.append(["match", ["get", col], val, True, False])
220
  combined_filters = ["all"] + filters
221
- if paint['property'] == "status": #show non-conserved and other-conserved areas
222
- conserved = ['match', ['get', 'status'], ['30x30-conserved', 'other-conserved', 'non-conserved'], True, False]
223
- combined_filters = ['any']+ [combined_filters] + [conserved]
224
  style = {
225
  "version": 8,
226
  "sources": {
@@ -233,7 +161,7 @@ def get_pmtiles_style(paint, alpha, filter_cols, filter_vals):
233
  {
234
  "id": "ca30x30",
235
  "source": "ca",
236
- "source-layer": "ca_30x30_stats",
237
  "type": "fill",
238
  "filter": combined_filters,
239
  "paint": {
@@ -244,6 +172,7 @@ def get_pmtiles_style(paint, alpha, filter_cols, filter_vals):
244
  ]
245
  }
246
  return style
 
247
 
248
  def get_pmtiles_style_llm(paint, ids):
249
  combined_filters = ["all", ["match", ["get", "id"], ids, True, False]]
@@ -259,13 +188,12 @@ def get_pmtiles_style_llm(paint, ids):
259
  {
260
  "id": "ca30x30",
261
  "source": "ca",
262
- "source-layer": "ca_30x30_stats",
263
  "type": "fill",
264
  "filter": combined_filters,
265
  "paint": {
266
  "fill-color": paint,
267
  "fill-opacity": 1,
268
- # "fill-extrusion-height": 1000
269
  }
270
  }
271
  ]
 
28
  mean_manageable_carbon = (_.manageable_carbon * _.acres).sum() / _.acres.sum(),
29
  mean_fire = (_.fire *_.acres).sum()/_.acres.sum(),
30
  mean_rxburn = (_.rxburn *_.acres).sum()/_.acres.sum(),
31
+ mean_disadvantaged = (_.disadvantaged_communities * _.acres).sum() / _.acres.sum(),
32
  mean_svi = (_.svi * _.acres).sum() / _.acres.sum(),
33
  )
34
  .mutate(percent_protected=_.percent_protected.round(1))
 
52
  filter_cols.append(column)
53
  filters.append(getattr(_, column).isin(colorby_vals[column]))
54
  combined_filter = reduce(lambda x, y: x & y, filters) #combining all the filters into ibis filter expression
55
+
56
+ if column == "status": #need to include non-conserved in summary stats
57
  combined_filter = (combined_filter) | (_.status.isin(['30x30-conserved','other-conserved','non-conserved']))
58
+
59
  df = get_summary(ca, combined_filter, [column], colors) # df used for charts
60
  df_tab = get_summary(ca, combined_filter, filter_cols, colors = None) #df used for printed table
61
  return df, df_tab
 
67
  alt.Theta("percent_protected:Q").stack(True),
68
  )
69
  pie = ( base
70
+ .mark_arc(innerRadius= 40, outerRadius=100, stroke = 'black', strokeWidth = .5)
71
  .encode(alt.Color("color:N").scale(None).legend(None),
72
  tooltip=['percent_protected', column])
73
  )
 
80
 
81
 
82
  def bar_chart(df, x, y, title): #display summary stats for color_by column
 
83
  #axis label angles / chart size
84
+ if x in ["manager_type",'status']: #labels are too long, making vertical
85
  angle = 270
86
  height = 373
87
+ elif x == 'ecoregion': # make labels vertical and figure taller
88
+ angle = 270
89
+ height = 430
90
  else: #other labels are horizontal
91
  angle = 0
92
  height = 310
 
101
  else:
102
  sort = 'x'
103
 
104
+ # modify label names in bar chart to fit in frame
105
+ label_transform = f"datum.{x}" # default; no change
106
+ if x == "access_type":
107
+ label_transform = f"replace(datum.{x}, ' Access', '')" #omit 'access' from access_type
108
+ elif x == "ecoregion":
109
+ label_transform = f"replace(datum.{x}, 'California', 'CA')" # Replace "California" with "CA"
110
+
111
  x_title = next(key for key, value in select_column.items() if value == x)
112
+ chart = alt.Chart(df).mark_bar(stroke = 'black', strokeWidth = .5).transform_calculate(
113
+ label=label_transform
114
  ).encode(
115
+ x=alt.X("label:N",
116
  axis=alt.Axis(labelAngle=angle, title=x_title, labelLimit = 200),
117
  sort=sort),
118
  y=alt.Y(y, axis=alt.Axis()),
119
+ color=alt.Color('color').scale(None),
120
+ ).properties(width="container", height=height, title = title)
 
 
 
 
 
 
 
 
121
  return chart
122
 
123
 
 
124
  def getButtons(style_options, style_choice, default_gap=None): #finding the buttons selected to use as filters
125
  column = style_options[style_choice]['property']
126
  opts = [style[0] for style in style_options[style_choice]['stops']]
 
135
  return d
136
 
137
 
 
138
  def getColorVals(style_options, style_choice):
139
  #df_tab only includes filters selected, we need to manually add "color_by" column (if it's not already a filter).
140
  column = style_options[style_choice]['property']
 
144
  return d
145
 
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  def get_pmtiles_style(paint, alpha, filter_cols, filter_vals):
148
  filters = []
149
  for col, val in zip(filter_cols, filter_vals):
150
  filters.append(["match", ["get", col], val, True, False])
151
  combined_filters = ["all"] + filters
 
 
 
152
  style = {
153
  "version": 8,
154
  "sources": {
 
161
  {
162
  "id": "ca30x30",
163
  "source": "ca",
164
+ "source-layer": "ca30x30",
165
  "type": "fill",
166
  "filter": combined_filters,
167
  "paint": {
 
172
  ]
173
  }
174
  return style
175
+
176
 
177
  def get_pmtiles_style_llm(paint, ids):
178
  combined_filters = ["all", ["match", ["get", "id"], ids, True, False]]
 
188
  {
189
  "id": "ca30x30",
190
  "source": "ca",
191
+ "source-layer": "ca30x30",
192
  "type": "fill",
193
  "filter": combined_filters,
194
  "paint": {
195
  "fill-color": paint,
196
  "fill-opacity": 1,
 
197
  }
198
  }
199
  ]
app/variables.py CHANGED
@@ -1,23 +1,20 @@
1
  # urls for main layer
2
- # ca_pmtiles = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/cpad-stats.pmtiles"
3
- # ca_parquet = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/cpad-stats.parquet"
4
 
5
- ca_pmtiles = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/ca_30x30_stats.pmtiles"
6
- ca_parquet = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/ca_30x30_stats.parquet"
7
 
8
  ca_area_acres = 1.014e8 #acres
9
  style_choice = "GAP Status Code"
10
 
11
-
12
  # urls for additional data layers
13
  url_sr = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/species-richness-ca/{z}/{x}/{y}.png"
14
  url_rsr = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/range-size-rarity/{z}/{x}/{y}.png"
15
  url_irr_carbon = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/ca_irrecoverable_c_2018_cog.tif"
16
  url_man_carbon = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/ca_manageable_c_2018_cog.tif"
17
- url_svi = "https://data.source.coop/cboettig/social-vulnerability/svi2020_us_county.pmtiles"
18
  url_justice40 = "https://data.source.coop/cboettig/justice40/disadvantaged-communities.pmtiles"
19
- url_calfire = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/cal_fire_2022.pmtiles"
20
- url_rxburn = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/cal_rxburn_2022.pmtiles"
 
21
 
22
  # colors for plotting
23
  private_access_color = "#DE881E" # orange
@@ -63,7 +60,6 @@ manager = {
63
  ['Tribal', tribal_color],
64
  ['Private', private_color],
65
  ['HOA', hoa_color],
66
- # ['None',white]
67
  ]
68
  }
69
 
@@ -73,7 +69,6 @@ easement = {
73
  'stops': [
74
  ['True', private_access_color],
75
  ['False', public_access_color],
76
- # ['None', white]
77
  ]
78
  }
79
 
@@ -83,7 +78,6 @@ year = {
83
  'stops': [
84
  ['pre-2024', year2023_color],
85
  ['2024', year2024_color],
86
- # ['None',white]
87
  ]
88
  }
89
 
@@ -95,8 +89,6 @@ access = {
95
  ['No Public Access', private_access_color],
96
  ['Unknown Access', "#bbbbbb"],
97
  ['Restricted Access', tribal_color],
98
- # ['None', white]
99
-
100
  ]
101
  }
102
 
@@ -117,39 +109,11 @@ status = {
117
  'stops': [
118
  ['30x30-conserved', "#26633d"],
119
  ['other-conserved', "#879647"],
120
- ['non-conserved', "#A9A9A9"]
121
  ]
122
  }
123
 
124
 
125
- # ecoregion = {
126
- # 'property': 'ecoregion',
127
- # 'type': 'categorical',
128
- # 'stops': [
129
- # ['Sierra Nevada Foothills', "#1f77b4"],
130
- # ['Southern Cascades', "#ff7f0e"],
131
- # ['Southeastern Great Basin', "#2ca02c"],
132
- # ['Southern California Mountains and Valleys', "#d62728"],
133
- # ['Sonoran Desert', "#9467bd"],
134
- # ['Northwestern Basin', "#8c564b"],
135
- # ['Colorado Desert', "#e377c2"],
136
- # ['Central Valley Coast Ranges', "#7f7f7f"],
137
- # ['Great Valley (South)', "#bcbd22"],
138
- # ['Sierra Nevada', "#17becf"],
139
- # ['Northern California Coast Ranges', "#aec7e8"],
140
- # ['Northern California Interior Coast Ranges', "#ffbb78"],
141
- # ['Mojave Desert', "#98df8a"],
142
- # ['Mono', "#ff9896"],
143
- # ['Southern California Coast', "#c5b0d5"],
144
- # ['Modoc Plateau', "#c49c94"],
145
- # ['Klamath Mountains', "#f7b6d2"],
146
- # ['Northern California Coast', "#c7c7c7"],
147
- # ['Great Valley (North)', "#dbdb8d"],
148
- # ['Central California Coast', "#9edae5"],
149
- # ['None', "#A9A9A9"]
150
- # ]
151
- # }
152
-
153
  ecoregion = {
154
  'property': 'ecoregion',
155
  'type': 'categorical',
@@ -157,33 +121,33 @@ ecoregion = {
157
  ['Sierra Nevada Foothills', "#1f77b4"],
158
  ['Southern Cascades', "#ff7f0e"],
159
  ['Southeastern Great Basin', "#2ca02c"],
160
- ['Southern CA Mountains and Valleys', "#d62728"],
161
  ['Sonoran Desert', "#9467bd"],
162
  ['Northwestern Basin', "#8c564b"],
163
  ['Colorado Desert', "#e377c2"],
164
  ['Central Valley Coast Ranges', "#7f7f7f"],
165
  ['Great Valley (South)', "#bcbd22"],
166
  ['Sierra Nevada', "#17becf"],
167
- ['Northern CA Coast Ranges', "#aec7e8"],
168
- ['Northern CA Interior Coast Ranges', "#ffbb78"],
169
  ['Mojave Desert', "#98df8a"],
170
  ['Mono', "#ff9896"],
171
- ['Southern CA Coast', "#c5b0d5"],
172
  ['Modoc Plateau', "#c49c94"],
173
  ['Klamath Mountains', "#f7b6d2"],
174
- ['Northern CA Coast', "#c7c7c7"],
175
  ['Great Valley (North)', "#dbdb8d"],
176
- ['Central CA Coast', "#9edae5"],
177
- ['None', "#A9A9A9"]
178
  ]
179
  }
180
 
181
 
182
 
 
183
  style_options = {
184
  "Year": year,
185
  "GAP Code": gap,
186
- "Status": status,
187
  "Ecoregion": ecoregion,
188
  "Manager Type": manager,
189
  "Easement": easement,
@@ -221,11 +185,78 @@ justice40_style = {
221
  }
222
  ]
223
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
  select_column = {
226
  "Year": "established",
227
  "GAP Code": "gap_code",
228
- "Status": "status",
229
  "Ecoregion": "ecoregion",
230
  "Manager Type": "manager_type",
231
  "Easement": "easement",
 
1
  # urls for main layer
2
+ ca_parquet = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/1bc81f4f0678143421f73645f0ba830aa1cb8617/ca-30x30.parquet"
3
+ ca_pmtiles = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/c08b22b9b506d444d0429a82f96f13e214341912/ca-30x30.pmtiles"
4
 
 
 
5
 
6
  ca_area_acres = 1.014e8 #acres
7
  style_choice = "GAP Status Code"
8
 
 
9
  # urls for additional data layers
10
  url_sr = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/species-richness-ca/{z}/{x}/{y}.png"
11
  url_rsr = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/range-size-rarity/{z}/{x}/{y}.png"
12
  url_irr_carbon = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/ca_irrecoverable_c_2018_cog.tif"
13
  url_man_carbon = "https://huggingface.co/datasets/boettiger-lab/ca-30x30/resolve/main/ca_manageable_c_2018_cog.tif"
 
14
  url_justice40 = "https://data.source.coop/cboettig/justice40/disadvantaged-communities.pmtiles"
15
+ url_calfire = 'https://minio.carlboettiger.info/public-fire/calfire-2023.pmtiles'
16
+ url_rxburn = 'https://minio.carlboettiger.info/public-fire/calfire-rxburn-2023.pmtiles'
17
+ url_svi = 'https://minio.carlboettiger.info/public-data/social-vulnerability/2022/SVI2022_US_tract.pmtiles'
18
 
19
  # colors for plotting
20
  private_access_color = "#DE881E" # orange
 
60
  ['Tribal', tribal_color],
61
  ['Private', private_color],
62
  ['HOA', hoa_color],
 
63
  ]
64
  }
65
 
 
69
  'stops': [
70
  ['True', private_access_color],
71
  ['False', public_access_color],
 
72
  ]
73
  }
74
 
 
78
  'stops': [
79
  ['pre-2024', year2023_color],
80
  ['2024', year2024_color],
 
81
  ]
82
  }
83
 
 
89
  ['No Public Access', private_access_color],
90
  ['Unknown Access', "#bbbbbb"],
91
  ['Restricted Access', tribal_color],
 
 
92
  ]
93
  }
94
 
 
109
  'stops': [
110
  ['30x30-conserved', "#26633d"],
111
  ['other-conserved', "#879647"],
112
+ ['non-conserved', white]
113
  ]
114
  }
115
 
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  ecoregion = {
118
  'property': 'ecoregion',
119
  'type': 'categorical',
 
121
  ['Sierra Nevada Foothills', "#1f77b4"],
122
  ['Southern Cascades', "#ff7f0e"],
123
  ['Southeastern Great Basin', "#2ca02c"],
124
+ ['Southern California Mountains and Valleys', "#d62728"],
125
  ['Sonoran Desert', "#9467bd"],
126
  ['Northwestern Basin', "#8c564b"],
127
  ['Colorado Desert', "#e377c2"],
128
  ['Central Valley Coast Ranges', "#7f7f7f"],
129
  ['Great Valley (South)', "#bcbd22"],
130
  ['Sierra Nevada', "#17becf"],
131
+ ['Northern California Coast Ranges', "#aec7e8"],
132
+ ['Northern California Interior Coast Ranges', "#ffbb78"],
133
  ['Mojave Desert', "#98df8a"],
134
  ['Mono', "#ff9896"],
135
+ ['Southern California Coast', "#c5b0d5"],
136
  ['Modoc Plateau', "#c49c94"],
137
  ['Klamath Mountains', "#f7b6d2"],
138
+ ['Northern California Coast', "#c7c7c7"],
139
  ['Great Valley (North)', "#dbdb8d"],
140
+ ['Central California Coast', "#9edae5"],
 
141
  ]
142
  }
143
 
144
 
145
 
146
+
147
  style_options = {
148
  "Year": year,
149
  "GAP Code": gap,
150
+ "30x30 Status": status,
151
  "Ecoregion": ecoregion,
152
  "Manager Type": manager,
153
  "Easement": easement,
 
185
  }
186
  ]
187
  }
188
+ fire_style = {"version": 8,
189
+ "sources": {
190
+ "source1": {
191
+ "type": "vector",
192
+ "url": "pmtiles://" + url_calfire,
193
+ "attribution": "CAL FIRE"
194
+ }
195
+ },
196
+ "layers": [
197
+ {
198
+ "id": "fire",
199
+ "source": "source1",
200
+ "source-layer": 'calfire2023',
201
+ "filter": [">=", ["get", "YEAR_"], 2013],
202
+
203
+ "type": "fill",
204
+ "paint": {
205
+ "fill-color": "#D22B2B",
206
+ }
207
+ }
208
+ ]
209
+ }
210
+ rx_style = {
211
+ "version": 8,
212
+ "sources": {
213
+ "source2": {
214
+ "type": "vector",
215
+ "url": "pmtiles://" + url_rxburn,
216
+ "attribution": "CAL FIRE"
217
+ }
218
+ },
219
+ "layers": [
220
+ {
221
+ "id": "rxburn",
222
+ "source": "source2",
223
+ "source-layer": 'calfirerxburn2023',
224
+ "filter": [">=", ["get", "YEAR_"], 2013],
225
+ "type": "fill",
226
+ "paint": {
227
+ "fill-color": "#702963",
228
+ }
229
+ }
230
+ ]
231
+ }
232
+
233
+
234
+ svi_style = {
235
+ "layers": [
236
+ {
237
+ "id": "svi",
238
+ "source": "svi",
239
+ "source-layer": "svi",
240
+ "filter": ["match", ["get", "ST_ABBR"], "CA", True, False],
241
+ "type": "fill",
242
+ "paint": {
243
+ "fill-color": [
244
+ "interpolate", ["linear"], ["get", "RPL_THEMES"],
245
+ 0, white,
246
+ 1, svi_color
247
+ ]
248
+ }
249
+ }
250
+ ]
251
+ }
252
+
253
+
254
+
255
 
256
  select_column = {
257
  "Year": "established",
258
  "GAP Code": "gap_code",
259
+ "30x30 Status": "status",
260
  "Ecoregion": "ecoregion",
261
  "Manager Type": "manager_type",
262
  "Easement": "easement",