cassiebuhler commited on
Commit
7128083
·
1 Parent(s): c3971fb

chatbot works but I don't love it

Browse files

It's weird to provide examples because of how we preprocessed the data.

Ex: reptile richness is not richness, it's the percent that an area overlaps with the top 20% of reptile rich areas.

This certainly limits the queries we can ask...

Files changed (3) hide show
  1. app/app.py +21 -23
  2. app/system_prompt.txt +25 -31
  3. app/utils.py +21 -21
app/app.py CHANGED
@@ -248,10 +248,8 @@ with st.container():
248
  with st.popover("💬 Example Queries"):
249
  '''
250
  Mapping queries:
251
- - Show me areas open to the public that are in the top 10% of species richness.
252
  - Show me all GAP 1 and 2 lands managed by The Nature Conservancy.
253
- - Show me state land smaller than 1000 acres, with a social vulnerability index in the 90th percentile.
254
- - Show me GAP 3 and 4 lands managed by BLM in the top 5% of range-size rarity.
255
  - Show me Joshua Tree National Park.
256
  - Show me all protected lands that have experienced forest fire over at least 50% of their area.
257
  - Show me the biggest protected area in California.
@@ -263,7 +261,7 @@ with st.container():
263
  - What is a GAP code?
264
  - What percentage of 30x30 conserved land has been impacted by wildfire?
265
  - What is the total acreage of areas designated as easements?
266
- - Who manages the land with the highest amount of irrecoverable carbon and highest social vulnerability index?
267
  '''
268
 
269
  st.info('If the map appears blank, queried data may be too small to see at the default zoom level. Check the table below the map, as query results will also be displayed there.', icon="ℹ️")
@@ -490,25 +488,25 @@ else:
490
 
491
 
492
  # charts displayed based on color_by variable
493
- amph_chart = bar_chart(df, column, 'mean_amph_richness', "ACE Amphibian Richness")
494
- reptile_chart = bar_chart(df, column, 'mean_reptile_richness', "ACE Reptile Richness")
495
- bird_chart = bar_chart(df, column, 'mean_bird_richness', "ACE Bird Richness")
496
- mammal_chart = bar_chart(df, column, 'mean_mammal_richness', "ACE Mammal Richness")
497
- rare_amph_chart = bar_chart(df, column, 'mean_rare_amph_richness', "ACE Rare Amphibian Richness")
498
- rare_reptile_chart = bar_chart(df, column, 'mean_rare_reptile_richness', "ACE Rare Reptile Richness")
499
- rare_bird_chart = bar_chart(df, column, 'mean_rare_bird_richness', "ACE Rare Bird Richness")
500
- rare_mammal_chart = bar_chart(df, column, 'mean_rare_mammal_richness', "ACE Rare Mammal Richness")
501
- end_amph_chart = bar_chart(df, column, 'mean_end_amph_richness', "ACE Endemic Amphibian Richness")
502
- end_reptile_chart = bar_chart(df, column, 'mean_end_reptile_richness', "ACE Endemic Reptile Richness")
503
- end_bird_chart = bar_chart(df, column, 'mean_end_bird_richness', "ACE Endemic Bird Richness")
504
- end_mammal_chart = bar_chart(df, column, 'mean_end_mammal_richness', "ACE Endemic Mammal Richness")
505
- plant_chart = bar_chart(df, column, 'mean_plant_richness', "Plant Richness")
506
- rarity_plant_chart = bar_chart(df, column, 'mean_rarityweight_endemic_plant_richness', "Plant Richness")
507
- wetlands_chart = bar_chart(df, column, 'mean_wetlands', "Wetlands")
508
- farmland_chart = bar_chart(df, column, 'mean_farmland', "Farmland")
509
- grazing_chart = bar_chart(df, column, 'mean_grazing', "Grazing land")
510
- DAC_chart = bar_chart(df, column, 'mean_disadvantaged', "Disadvantaged Communities")
511
- low_income_chart = bar_chart(df, column, 'mean_low_income', "Low-Income Communities")
512
 
513
 
514
 
 
248
  with st.popover("💬 Example Queries"):
249
  '''
250
  Mapping queries:
 
251
  - Show me all GAP 1 and 2 lands managed by The Nature Conservancy.
252
+ - Show me GAP 3 and 4 lands with the top 5% of rare amphibian richness.
 
253
  - Show me Joshua Tree National Park.
254
  - Show me all protected lands that have experienced forest fire over at least 50% of their area.
255
  - Show me the biggest protected area in California.
 
261
  - What is a GAP code?
262
  - What percentage of 30x30 conserved land has been impacted by wildfire?
263
  - What is the total acreage of areas designated as easements?
264
+ - Who manages the land with the highest percentage of wetlands?
265
  '''
266
 
267
  st.info('If the map appears blank, queried data may be too small to see at the default zoom level. Check the table below the map, as query results will also be displayed there.', icon="ℹ️")
 
488
 
489
 
490
  # charts displayed based on color_by variable
491
+ amph_chart = bar_chart(df, column, 'percent_amph_richness', "ACE Amphibian Richness")
492
+ reptile_chart = bar_chart(df, column, 'percent_reptile_richness', "ACE Reptile Richness")
493
+ bird_chart = bar_chart(df, column, 'percent_bird_richness', "ACE Bird Richness")
494
+ mammal_chart = bar_chart(df, column, 'percent_mammal_richness', "ACE Mammal Richness")
495
+ rare_amph_chart = bar_chart(df, column, 'percent_rare_amph_richness', "ACE Rare Amphibian Richness")
496
+ rare_reptile_chart = bar_chart(df, column, 'percent_rare_reptile_richness', "ACE Rare Reptile Richness")
497
+ rare_bird_chart = bar_chart(df, column, 'percent_rare_bird_richness', "ACE Rare Bird Richness")
498
+ rare_mammal_chart = bar_chart(df, column, 'percent_rare_mammal_richness', "ACE Rare Mammal Richness")
499
+ end_amph_chart = bar_chart(df, column, 'percent_end_amph_richness', "ACE Endemic Amphibian Richness")
500
+ end_reptile_chart = bar_chart(df, column, 'percent_end_reptile_richness', "ACE Endemic Reptile Richness")
501
+ end_bird_chart = bar_chart(df, column, 'percent_end_bird_richness', "ACE Endemic Bird Richness")
502
+ end_mammal_chart = bar_chart(df, column, 'percent_end_mammal_richness', "ACE Endemic Mammal Richness")
503
+ plant_chart = bar_chart(df, column, 'percent_plant_richness', "Plant Richness")
504
+ rarity_plant_chart = bar_chart(df, column, 'percent_rarityweight_endemic_plant_richness', "Plant Richness")
505
+ wetlands_chart = bar_chart(df, column, 'percent_wetlands', "Wetlands")
506
+ farmland_chart = bar_chart(df, column, 'percent_farmland', "Farmland")
507
+ grazing_chart = bar_chart(df, column, 'percent_grazing', "Grazing land")
508
+ DAC_chart = bar_chart(df, column, 'percent_disadvantaged', "Disadvantaged Communities")
509
+ low_income_chart = bar_chart(df, column, 'percent_low_income', "Low-Income Communities")
510
 
511
 
512
 
app/system_prompt.txt CHANGED
@@ -45,16 +45,16 @@ Ensure the response contains only this JSON object, with no additional text, for
45
  - "acres": Land acreage; measures the size of the area.
46
  - "type": Physical type of area, either "Land" or "Water".
47
  - "county": County name.
48
- - "climate_zone": There are 10 climate zones.
49
  - "habitat_type": California vegetation by wildlife habitat relationship type. There are 13 habitat types: 'Water', 'Conifer Forest', 'Shrub', 'Barren/Other',
50
  'Hardwood Forest', 'Herbaceous', 'Urban', 'Hardwood Woodland','Desert Shrub', 'Conifer Woodland', 'Wetland', 'Desert Woodland', and 'Agriculture'.
51
- - "plant_richness": Count of plant species recorded in that area.
52
- - "rarityweighted_endemic_plant_richness": Count of rarity-weighted endemic plant species recorded in that area.
53
  - "resilient_connected_network": Categorical variable describing the resilience and connectiveness of that area.
54
  There are 12 biodiversity columns of 4 taxonomic groups (amphibian, birds, mammals, reptiles) measured in 3 ways:
55
- 1) "ACE_amphibian_richness", "ACE_reptile_richness", "ACE_bird_richness", and "ACE_mammal_richness" measure native species richness of overall native diversity the top 20%;
56
- 2) "ACE_rare_amphibian_richness", "ACE_rare_reptile_richness", "ACE_rare_bird_richness", and "ACE_rare_mammal_richness" measure diversity of rare species in the top 5%.
57
- 3) "ACE_endemic_amphibian_richness", "ACE_endemic_reptile_richness", "ACE_endemic_bird_richness", and "ACE_endemic_mammal_richness" are a weighted measure of endemism that highlights areas that support unique species of limited range. Irreplaceable species in the top 5%.
58
  - "wetlands": How much an area overlaps with wetlands, specifically freshwater emergent wetland, freshwater forested/shrub wetland, or estuarine and marine wetland.
59
  - "fire": The percentage of the area burned by fires from (2014-2023). Areas can burn more than once, thus the percentage can be above 1
60
  - "farmland": How much an area overlaps with farmland (specifically prime, unique, of statewide or local importance).
@@ -89,16 +89,14 @@ example_assistant: {{"sql_query":
89
  }}
90
 
91
  ## Example:
92
- example_user: "Who manages the land with the worst biodiversity and highest SVI?"
93
  example_assistant: {{"sql_query":
94
  SELECT "manager", "richness", "svi"
95
  FROM mydata
96
  GROUP BY "manager"
97
- ORDER BY "richness" ASC, "svi" DESC
98
  LIMIT 1;
99
- "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.
100
-
101
- 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)."
102
  }}
103
 
104
  ## Example:
@@ -112,30 +110,26 @@ example_assistant: {{"sql_query":
112
  "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."
113
 
114
  ## Example:
115
- example_user: "Show me the 50 most biodiverse areas found in disadvantaged communities."
116
  example_assistant: {{"sql_query":
117
- SELECT "id", "geom", "name", "acres", "richness", "disadvantaged_communities" FROM mydata
118
- WHERE "disadvantaged_communities" > 0
119
- ORDER BY "richness" DESC
120
  LIMIT 50;
121
- "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.
122
 
123
  The results are sorted in descending order by biodiversity richness (highest biodiversity first), and only areas with a `disadvantaged_communities` value greater than 0 (indicating some portion of the area overlaps with a disadvantaged community) are included."
124
  }}
125
 
126
  ## Example:
127
- example_user: "Show me federally managed gap 3 lands that are in the top 5% of biodiversity richness and have experienced forest fire over at least 50% of their area"
128
  sql_query:
129
- WITH temp AS (
130
- SELECT PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY "richness") AS richness_95_percentile
131
- FROM mydata
132
- )
133
- SELECT "id", "geom", "name", "acres", "richness", "gap_code", "fire"
134
  FROM mydata
135
  WHERE "gap_code" = 3
136
  AND "fire" >= 0.5
137
- and "manager_type" = 'Federal'
138
- AND "richness" > (SELECT richness_95_percentile FROM temp);
139
 
140
  ## Example:
141
  example_user: "What is the total acreage of areas designated as easements?
@@ -145,23 +139,23 @@ sql_query:
145
  WHERE "easement" = 'True';
146
 
147
  ## Example:
148
- example_user: "Which ecoregions are in the top 10% of range-size rarity?"
149
  sql_query:
150
  WITH temp AS (
151
- SELECT PERCENTILE_CONT(0.90) WITHIN GROUP (ORDER BY "rsr") AS rsr_90_percentile
152
  FROM mydata
153
  )
154
  SELECT "ecoregion"
155
  FROM mydata
156
- WHERE "rsr" > (SELECT rsr_90_percentile FROM temp);
157
 
158
  ## Example:
159
- example_user: "Show me protected lands in disadvantaged communities that have had prescribed fires in at least 30% of its area."
160
  sql_query:
161
- SELECT "id", "geom", "name", "acres", "rxburn", "percent_disadvantaged"
162
  FROM mydata
163
- WHERE "percent_disadvantaged" > 0
164
- AND "percent_rxburn_10yr" >= 0.3;
165
 
166
 
167
 
 
45
  - "acres": Land acreage; measures the size of the area.
46
  - "type": Physical type of area, either "Land" or "Water".
47
  - "county": County name.
48
+ - "climate_zone": 10 climate zones.
49
  - "habitat_type": California vegetation by wildlife habitat relationship type. There are 13 habitat types: 'Water', 'Conifer Forest', 'Shrub', 'Barren/Other',
50
  'Hardwood Forest', 'Herbaceous', 'Urban', 'Hardwood Woodland','Desert Shrub', 'Conifer Woodland', 'Wetland', 'Desert Woodland', and 'Agriculture'.
51
+ - "plant_richness": Overlap of top 20% of plant species recorded in that area.
52
+ - "rarityweighted_endemic_plant_richness": Overlap of top 20% rarity-weighted endemic plant species recorded in that area.
53
  - "resilient_connected_network": Categorical variable describing the resilience and connectiveness of that area.
54
  There are 12 biodiversity columns of 4 taxonomic groups (amphibian, birds, mammals, reptiles) measured in 3 ways:
55
+ 1) "ACE_amphibian_richness", "ACE_reptile_richness", "ACE_bird_richness", and "ACE_mammal_richness" measure native species richness. These fields represents how much an area overlaps with the top 20% of richness.
56
+ 2) "ACE_rare_amphibian_richness", "ACE_rare_reptile_richness", "ACE_rare_bird_richness", and "ACE_rare_mammal_richness" measure diversity of rare species. These fields represents how much an area overlaps with the top 5% of rare species.
57
+ 3) "ACE_endemic_amphibian_richness", "ACE_endemic_reptile_richness", "ACE_endemic_bird_richness", and "ACE_endemic_mammal_richness" are a weighted measure of endemism that highlights areas that support unique species of limited range. These fields represents how much an area overlaps with the top 5% of these irreplaceable species.
58
  - "wetlands": How much an area overlaps with wetlands, specifically freshwater emergent wetland, freshwater forested/shrub wetland, or estuarine and marine wetland.
59
  - "fire": The percentage of the area burned by fires from (2014-2023). Areas can burn more than once, thus the percentage can be above 1
60
  - "farmland": How much an area overlaps with farmland (specifically prime, unique, of statewide or local importance).
 
89
  }}
90
 
91
  ## Example:
92
+ example_user: "Who manages the land with the highest rare amphibian richness?"
93
  example_assistant: {{"sql_query":
94
  SELECT "manager", "richness", "svi"
95
  FROM mydata
96
  GROUP BY "manager"
97
+ ORDER BY "ACE_rare_amphibian_richness" DESC
98
  LIMIT 1;
99
+ "explanation": "I identified the land manager with the highest rare amphibian richness by analyzing the column: `ACE_rare_amphibian_richness`, which has the percent of rare amphibians in the top 5%. I sorted the data in descending order (highest biodiversity first). 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)."
 
 
100
  }}
101
 
102
  ## Example:
 
110
  "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."
111
 
112
  ## Example:
113
+ example_user: "Show me the 50 most bird biodiverse areas found in disadvantaged communities."
114
  example_assistant: {{"sql_query":
115
+ SELECT "id", "geom", "name", "acres", "ACE_bird_richness", "DAC" FROM mydata
116
+ WHERE "DAC" > 0
117
+ ORDER BY "ACE_bird_richness" DESC
118
  LIMIT 50;
119
+ "explanation": "I used the `ACE_bird_richness` column to measure bird biodiversity and the `DAC` column to identify areas located in disadvantaged communities. The `DAC` 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.
120
 
121
  The results are sorted in descending order by biodiversity richness (highest biodiversity first), and only areas with a `disadvantaged_communities` value greater than 0 (indicating some portion of the area overlaps with a disadvantaged community) are included."
122
  }}
123
 
124
  ## Example:
125
+ example_user: "Show me federally managed gap 3 lands that are in the top 5% of endemic mammal richness and have experienced forest fire over at least 50% of their area"
126
  sql_query:
127
+ SELECT "id", "geom", "name", "acres", "ACE_endemic_mammal_richness", "gap_code", "fire"
 
 
 
 
128
  FROM mydata
129
  WHERE "gap_code" = 3
130
  AND "fire" >= 0.5
131
+ AND "manager_type" = 'Federal'
132
+ AND "ACE_endemic_mammal_richness" > 0;
133
 
134
  ## Example:
135
  example_user: "What is the total acreage of areas designated as easements?
 
139
  WHERE "easement" = 'True';
140
 
141
  ## Example:
142
+ example_user: "Which ecoregions are in the top 50% of farmland?"
143
  sql_query:
144
  WITH temp AS (
145
+ SELECT PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY "farmland") AS farmland_50_percentile
146
  FROM mydata
147
  )
148
  SELECT "ecoregion"
149
  FROM mydata
150
+ WHERE "farmland" > (SELECT farmland_90_percentile FROM temp);
151
 
152
  ## Example:
153
+ example_user: "Show me protected lands in disadvantaged communities that have wetlands in at least 30% of its area."
154
  sql_query:
155
+ SELECT "id", "geom", "name", "acres", "wetlands", "DAC"
156
  FROM mydata
157
+ WHERE "DAC" > 0
158
+ AND "wetlands" >= 0.3;
159
 
160
 
161
 
app/utils.py CHANGED
@@ -95,26 +95,26 @@ def get_summary(ca, combined_filter, column, main_group, colors = None):
95
  df = (df.group_by(*column)
96
  .aggregate(percent_CA=(_.acres.sum() / ca_area_acres),
97
  acres=_.acres.sum(),
98
- mean_amph_richness =(_.ACE_amphibian_richness * _.acres).sum() / _.acres.sum(),
99
- mean_reptile_richness=(_.ACE_reptile_richness * _.acres).sum() / _.acres.sum(),
100
- mean_bird_richness=(_.ACE_bird_richness * _.acres).sum() / _.acres.sum(),
101
- mean_mammal_richness=(_.ACE_mammal_richness * _.acres).sum() / _.acres.sum(),
102
- mean_rare_amph_richness =(_.ACE_rare_amphibian_richness * _.acres).sum() / _.acres.sum(),
103
- mean_rare_reptile_richness=(_.ACE_rare_reptile_richness * _.acres).sum() / _.acres.sum(),
104
- mean_rare_bird_richness=(_.ACE_rare_bird_richness * _.acres).sum() / _.acres.sum(),
105
- mean_rare_mammal_richness=(_.ACE_rare_mammal_richness * _.acres).sum() / _.acres.sum(),
106
- mean_end_amph_richness =(_.ACE_endemic_amphibian_richness * _.acres).sum() / _.acres.sum(),
107
- mean_end_reptile_richness=(_.ACE_endemic_reptile_richness * _.acres).sum() / _.acres.sum(),
108
- mean_end_bird_richness=(_.ACE_endemic_bird_richness * _.acres).sum() / _.acres.sum(),
109
- mean_end_mammal_richness=(_.ACE_endemic_mammal_richness * _.acres).sum() / _.acres.sum(),
110
- mean_plant_richness=(_.plant_richness * _.acres).sum()/_.acres.sum(),
111
- mean_rarityweight_endemic_plant_richness=(_.rarityweighted_endemic_plant_richness * _.acres).sum()/_.acres.sum(),
112
- mean_wetlands=(_.wetlands * _.acres).sum()/_.acres.sum(),
113
- mean_fire=(_.fire * _.acres).sum() / _.acres.sum(),
114
- mean_farmland=(_.farmland * _.acres).sum() / _.acres.sum(),
115
- mean_grazing=(_.grazing * _.acres).sum() / _.acres.sum(),
116
- mean_disadvantaged=(_.DAC * _.acres).sum() / _.acres.sum(),
117
- mean_low_income=(_.low_income * _.acres).sum() / _.acres.sum()
118
  )
119
  .mutate(percent_CA=_.percent_CA.round(5), acres=_.acres.round(0))
120
  )
@@ -324,7 +324,7 @@ def get_chart_settings(x, stacked):
324
  "mean_svi": "SVI (Mean)", "mean_fire": "Fire (Mean)", "mean_rxburn": "Rx Fire (Mean)"
325
  }
326
 
327
- angle = 270 if x in ["manager_type", "ecoregion"] else 0
328
  height = 250 if stacked else 400 if x == "ecoregion" else 350 if x == "manager_type" else 300
329
 
330
  return sort_options.get(x, "x"), angle, height, y_titles.get(x, x)
 
95
  df = (df.group_by(*column)
96
  .aggregate(percent_CA=(_.acres.sum() / ca_area_acres),
97
  acres=_.acres.sum(),
98
+ percent_amph_richness =(_.ACE_amphibian_richness * _.acres).sum() / _.acres.sum(),
99
+ percent_reptile_richness=(_.ACE_reptile_richness * _.acres).sum() / _.acres.sum(),
100
+ percent_bird_richness=(_.ACE_bird_richness * _.acres).sum() / _.acres.sum(),
101
+ percent_mammal_richness=(_.ACE_mammal_richness * _.acres).sum() / _.acres.sum(),
102
+ percent_rare_amph_richness =(_.ACE_rare_amphibian_richness * _.acres).sum() / _.acres.sum(),
103
+ percent_rare_reptile_richness=(_.ACE_rare_reptile_richness * _.acres).sum() / _.acres.sum(),
104
+ percent_rare_bird_richness=(_.ACE_rare_bird_richness * _.acres).sum() / _.acres.sum(),
105
+ percent_rare_mammal_richness=(_.ACE_rare_mammal_richness * _.acres).sum() / _.acres.sum(),
106
+ percent_end_amph_richness =(_.ACE_endemic_amphibian_richness * _.acres).sum() / _.acres.sum(),
107
+ percent_end_reptile_richness=(_.ACE_endemic_reptile_richness * _.acres).sum() / _.acres.sum(),
108
+ percent_end_bird_richness=(_.ACE_endemic_bird_richness * _.acres).sum() / _.acres.sum(),
109
+ percent_end_mammal_richness=(_.ACE_endemic_mammal_richness * _.acres).sum() / _.acres.sum(),
110
+ percent_plant_richness=(_.plant_richness * _.acres).sum()/_.acres.sum(),
111
+ percent_rarityweight_endemic_plant_richness=(_.rarityweighted_endemic_plant_richness * _.acres).sum()/_.acres.sum(),
112
+ percent_wetlands=(_.wetlands * _.acres).sum()/_.acres.sum(),
113
+ percent_fire=(_.fire * _.acres).sum() / _.acres.sum(),
114
+ percent_farmland=(_.farmland * _.acres).sum() / _.acres.sum(),
115
+ percent_grazing=(_.grazing * _.acres).sum() / _.acres.sum(),
116
+ percent_disadvantaged=(_.DAC * _.acres).sum() / _.acres.sum(),
117
+ percent_low_income=(_.low_income * _.acres).sum() / _.acres.sum()
118
  )
119
  .mutate(percent_CA=_.percent_CA.round(5), acres=_.acres.round(0))
120
  )
 
324
  "mean_svi": "SVI (Mean)", "mean_fire": "Fire (Mean)", "mean_rxburn": "Rx Fire (Mean)"
325
  }
326
 
327
+ angle = 270 if x in ["manager_type", "ecoregion", "status", "habitat_type", "resilient_connected_network"] else 0
328
  height = 250 if stacked else 400 if x == "ecoregion" else 350 if x == "manager_type" else 300
329
 
330
  return sort_options.get(x, "x"), angle, height, y_titles.get(x, x)