diff --git a/climate_emotions_map/app.py b/climate_emotions_map/app.py
index 2f305c8..4d949c0 100644
--- a/climate_emotions_map/app.py
+++ b/climate_emotions_map/app.py
@@ -16,7 +16,7 @@
from . import utility as utils
from .data_loader import NATIONAL_SAMPLE_SIZE, SURVEY_DATA
-from .layout import SINGLE_SUBQUESTION_FIG_KW, construct_layout
+from .layout import MAP_LAYOUT, SINGLE_SUBQUESTION_FIG_KW, construct_layout
from .make_descriptive_plots import make_descriptive_plots
from .make_map import make_map
from .make_stacked_bar_plots import make_stacked_bar
@@ -62,10 +62,22 @@ def update_state_and_disable_state_select_and_party_switch_interaction(
and disable the party stratify switch when a specific state is selected (i.e., not None).
"""
if ctx.triggered_id == "us-map":
- map_selected_state = figure["points"][0]["customdata"][0]
-
- if is_party_stratify_checked or map_selected_state == selected_state:
+ if is_party_stratify_checked:
raise PreventUpdate
+
+ point = figure["points"][0]
+
+ # TODO: This is a temporary fix to handle the edge case where the exact same point (coords)
+ # on the map is selected twice, in which case the customdata key is for some reason missing
+ # from the clickData of the second click.
+ # This workaround assumes that this can only happen in cases where the clicked state is
+ # the same as the currently selected state, and thus will deselect the state in this case.
+ if "customdata" not in point:
+ return None, no_update, False, False
+
+ map_selected_state = point["customdata"][0]
+ if map_selected_state == selected_state:
+ return None, no_update, False, False
return (
map_selected_state,
no_update,
@@ -130,6 +142,7 @@ def update_sample_descriptive_plot(state):
@callback(
Output("impact-select", "value"),
Input("question-select", "value"),
+ prevent_initial_call=True,
)
def reset_impact_select(question_value):
"""Reset the impact select dropdown when a new question is selected."""
@@ -157,6 +170,7 @@ def update_map_title(impact, options):
Input("question-select", "value"),
Input("impact-select", "value"),
],
+ prevent_initial_call=True,
)
def update_map_subtitle(question_value, impact):
"""Update the map subtitle based on the selected question and whether an impact is selected."""
@@ -191,8 +205,9 @@ def update_map(question_value, state, impact):
outcome=DEFAULT_QUESTION["outcome"],
clicked_state=state,
impact=impact,
+ colormap_range_padding=MAP_LAYOUT["colormap_range_padding"],
+ margins=MAP_LAYOUT["margin"],
# opinion_colormap=OPINION_COLORMAP,
- show_impact_as_gradient=True,
# impact_colormap=IMPACT_COLORMAP,
)
@@ -259,6 +274,7 @@ def toggle_selected_question_bar_plot_visibility(impact):
@callback(
Output("all-questions-title", "children"),
Input("state-select", "value"),
+ prevent_initial_call=True,
)
def update_all_questions_title(state):
"""Update the title for the section for all questions based on the selected state."""
diff --git a/climate_emotions_map/layout.py b/climate_emotions_map/layout.py
index 86d2285..229d12b 100644
--- a/climate_emotions_map/layout.py
+++ b/climate_emotions_map/layout.py
@@ -21,12 +21,15 @@
"weighted_descriptives": "*N are unweighted while proportions are weighted according to census estimates for age, sex, race, and ethnicity",
}
+MAP_LAYOUT = {
+ "margin": {"l": 15, "r": 15, "t": 15, "b": 15},
+ "colormap_range_padding": 0,
+}
+
SINGLE_SUBQUESTION_FIG_KW = {
"fontsize": 10,
- # NOTE: Can calculate same actual height as create_bar_plots_for_question with:
- # ( default height - (default-set margin top) - (default-set margin bottom) )
- "height": 105,
- "margin": {"l": 30, "r": 30, "t": 5, "b": 20},
+ "height": 120,
+ "margin": {"l": 30, "r": 30, "t": 10, "b": 20},
}
@@ -173,7 +176,7 @@ def create_design_credit():
long_credit = dmc.Text(
children=[
dmc.Text(
- "Alyssa Dai, Nikhil Bhagwat, Rémi Gau, Arman Jahanpour, Kendra Oudyk, Sebastian Urchs, Michelle Wang"
+ "Alyssa Dai, Michelle Wang, Nikhil Bhagwat, Arman Jahanpour, Kendra Oudyk, Rémi Gau, Sebastian Urchs"
),
dmc.Anchor(
"ORIGAMI Lab, PI: Jean-Baptiste Poline",
@@ -326,22 +329,25 @@ def create_impact_dropdown():
def create_map_plot():
"""Create the component holding the cloropleth map plot of US states."""
us_map = dmc.Container(
- # TODO: Make map margins smaller (or create a param for this, maybe), and make figure height larger (?)
dcc.Graph(
id="us-map",
figure=make_map(
question=DEFAULT_QUESTION["question"],
sub_question=DEFAULT_QUESTION["sub_question"],
outcome=DEFAULT_QUESTION["outcome"],
+ colormap_range_padding=MAP_LAYOUT["colormap_range_padding"],
+ margins=MAP_LAYOUT["margin"],
# opinion_colormap=OPINION_COLORMAP,
),
# vh = % of viewport height
# TODO: Revisit once plot margins are adjusted
+ config={"scrollZoom": False},
style={"height": "65vh"},
),
- # sets max width
+ # set max width
# TODO: Revisit once plot margins are adjusted
- size="lg",
+ # style={"maxWidth": "70vw"},
+ size="xl",
)
return us_map
diff --git a/climate_emotions_map/make_map.py b/climate_emotions_map/make_map.py
index fcc8664..56d587d 100644
--- a/climate_emotions_map/make_map.py
+++ b/climate_emotions_map/make_map.py
@@ -108,8 +108,8 @@ def make_map(
# constants
col_location = "state"
col_color = "percentage"
- col_color_opinion = f"{col_color} (opinion)"
- col_color_impact = f"{col_color} (impact)"
+ col_color_opinion = f"{col_color}
(endorsement)"
+ col_color_impact = f"{col_color}
(weather event)"
# default values
if opinion_colormap is None:
@@ -194,6 +194,9 @@ def make_map(
colorbar_title=col_gradient.capitalize(),
name="main_map",
hoverinfo="none", # no hoverbox but click events are still emitted (?)
+ # TODO: revisit
+ # position colorbar closer to plot area (map)
+ colorbar={"x": 1},
)
# add outline for clicked state
@@ -241,7 +244,7 @@ def make_map(
hovertemplate=(
"%{customdata[0]}"
"
Sample size: %{customdata[1]}"
- f"
{col_gradient.capitalize()}: %{{z:.1f}}%"
+ f"
{col_gradient.replace('
', ' ').capitalize()}: %{{z:.1f}}%"
f"{hovertemplate_extra}"
""
),
diff --git a/climate_emotions_map/make_stacked_bar_plots.py b/climate_emotions_map/make_stacked_bar_plots.py
index d549c54..797c056 100644
--- a/climate_emotions_map/make_stacked_bar_plots.py
+++ b/climate_emotions_map/make_stacked_bar_plots.py
@@ -204,7 +204,6 @@ def plot_bars(
category_orders = {facet_var: facet_order}
# Define custom hover data
- # TODO: Do we need the raw outcomes in the hover data? "outcome" / color column
custom_data = ["full_text"]
# hides the secondary box that appears when hovering over the bars
hovertemplate = "
".join(
diff --git a/climate_emotions_map/utility.py b/climate_emotions_map/utility.py
index d6f354d..ff4694e 100644
--- a/climate_emotions_map/utility.py
+++ b/climate_emotions_map/utility.py
@@ -25,7 +25,6 @@
def get_state_options():
"""Get the options for the state dropdown."""
- # TODO: The state values include cluster labels in parentheses, e.g. (Cluster F). Can remove from label if desired.
return [
{"label": state, "value": state}
for state in SURVEY_DATA["samplesizes_state.tsv"]["state"]