Skip to content

Commit cafbdd2

Browse files
Chiu PeterChiu Peter
authored andcommitted
update graph by wrapping it in html.Div
1 parent 0b37a62 commit cafbdd2

File tree

1 file changed

+46
-34
lines changed

1 file changed

+46
-34
lines changed

crystal_toolkit/components/pourbaix.py

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,26 @@ def clean_formula(formula):
571571
# Subscript coefficients
572572
return re.sub(r"([A-Za-z\(\)])([\d\.]+)", r"\1<sub>\2</sub>", clean_formula)
573573

574+
def get_figure_div(self, figure):
575+
"""
576+
Intentionally update the graph by wrapping it in an `html.Div` instead of directly modifying `go.Figure` or `dcc.Graph`.
577+
This is because, after resetting the axes (e.g., zooming in/out), the updated axes may not match the original ones.
578+
This behavior appears to be a long-standing issue in Dash.
579+
580+
Reference:
581+
https://community.plotly.com/t/dash-reset-axes-range-not-updating-if-ranges-specified-in-layout/25839/3
582+
"""
583+
if figure is None:
584+
figure = go.Figure(layout={**PourbaixDiagramComponent.empty_plot_style})
585+
586+
return html.Div(
587+
dcc.Graph(
588+
figure=figure,
589+
responsive=True,
590+
config={"displayModeBar": False, "displaylogo": False},
591+
),
592+
)
593+
574594
@property
575595
def _sub_layouts(self) -> dict[str, Component]:
576596
options = html.Div(
@@ -623,7 +643,7 @@ def _sub_layouts(self) -> dict[str, Component]:
623643
message=f"Illegal concentration entry! Must be between {MIN_CONCENTRATION} and {MAX_CONCENTRATION} M",
624644
),
625645
],
626-
id=self.id("comp-panel"),
646+
id=self.id("conc-panel"),
627647
style={"display": "none"},
628648
),
629649
html.Div(id=self.id("element_specific_controls")),
@@ -661,15 +681,20 @@ def _sub_layouts(self) -> dict[str, Component]:
661681
]
662682
)
663683

664-
graph = html.Div(
665-
dcc.Graph(
666-
figure=go.Figure(layout={**PourbaixDiagramComponent.empty_plot_style}),
667-
id=self.id("graph"),
668-
responsive=True,
669-
config={"displayModeBar": False, "displaylogo": False},
684+
graph = (
685+
html.Div(
686+
dcc.Graph(
687+
figure=go.Figure(
688+
layout={**PourbaixDiagramComponent.empty_plot_style}
689+
),
690+
responsive=True,
691+
config={"displayModeBar": False, "displaylogo": False},
692+
),
693+
style={"minHeight": "500px"},
694+
id=self.id("graph-panel"),
670695
),
671-
style={"minHeight": "500px"},
672696
)
697+
# html.H5("Zoom in by selecting an area of interest, and double-click to return to the original view.")
673698

674699
return {"graph": graph, "options": options}
675700

@@ -699,16 +724,13 @@ def update_heatmap_choices(entries, mat_detials, filter_solids):
699724
solid_entries = [
700725
entry for entry in entries_obj if entry.phase_type == "Solid"
701726
]
702-
print("yeee7")
703-
print(entries)
727+
704728
if filter_solids:
705729
# O is 2.46 b/c pbx entry finds energies referenced to H2O
706730
entries_HO = [ComputedEntry("H", 0), ComputedEntry("O", 2.46)]
707731
solid_pd = PhaseDiagram(solid_entries + entries_HO)
708732
entries_obj = list(set(solid_pd.stable_entries) - set(entries_HO))
709733
entries = [en.as_dict() for en in entries_obj]
710-
print("yeee8")
711-
print(entries)
712734

713735
options = []
714736
for entry in entries:
@@ -770,13 +792,11 @@ def update_heatmap_choices(entries, mat_detials, filter_solids):
770792
Output(self.id("comp-text"), "value"),
771793
Output(self.id("composition-title"), "children"),
772794
Input(self.id(), "data"),
773-
# Input(self.get_kwarg_id("heatmap_choice"), "value"),
774-
# State(self.get_kwarg_id("show_heatmap"), "value"),
775795
prevent_initial_call=True,
776796
)
777797
def update_element_specific_sliders(
778798
entries,
779-
): # , heatmap_choice, show_heatmap):
799+
):
780800
"""
781801
When pourbaix entries input, add concentration and composition options
782802
"""
@@ -785,23 +805,14 @@ def update_element_specific_sliders(
785805

786806
elements = set()
787807

788-
# kwargs = self.reconstruct_kwargs_from_state()
789-
# heatmap_choice = kwargs.get("heatmap_choice", None)
790-
# show_heatmap = kwargs.get("show_heatmap", False)
791-
# heatmap_entry = None
792-
793808
for entry in entries:
794809
if entry["entry_id"].startswith("mp"):
795810
composition = Composition(entry["entry"]["composition"])
796811
elements.update(composition.elements)
797-
# if entry["entry_id"] == heatmap_choice:
798-
# heatmap_entry = entry
799812

800813
# exclude O and H
801814
elements = elements - ELEMENTS_HO
802815

803-
# comp_defaults = {element: 1 / len(elements) for element in elements}
804-
805816
comp_inputs = []
806817
conc_inputs = []
807818
for element in sorted(elements):
@@ -992,7 +1003,7 @@ def get_pourbaix_diagram(pourbaix_entries, **kwargs):
9921003
return PourbaixDiagram(pourbaix_entries, **kwargs)
9931004

9941005
@app.callback(
995-
Output(self.id("graph"), "figure"),
1006+
Output(self.id("graph-panel"), "children"),
9961007
Output(self.id("invalid-comp-alarm"), "displayed"),
9971008
Output(self.id("invalid-conc-alarm"), "displayed"),
9981009
Input(self.id(), "data"),
@@ -1020,7 +1031,7 @@ def make_figure(
10201031
if len(raw_comp_list) != len(elements):
10211032
logger.error("Invalid composition input!")
10221033
return (
1023-
go.Figure(layout={**PourbaixDiagramComponent.empty_plot_style}),
1034+
self.get_figure_div(),
10241035
True,
10251036
False,
10261037
)
@@ -1030,7 +1041,7 @@ def make_figure(
10301041
except Exception:
10311042
logger.error("Invalid composition input!")
10321043
return (
1033-
go.Figure(layout={**PourbaixDiagramComponent.empty_plot_style}),
1044+
self.get_figure_div(),
10341045
True,
10351046
False,
10361047
)
@@ -1078,10 +1089,9 @@ def make_figure(
10781089
for key, val in kwargs.items():
10791090
if "conc" in key: # keys are encoded like "conc-Ag"
10801091
if val is None:
1092+
# if the input is out of pre-defined range, Input will get None
10811093
return (
1082-
go.Figure(
1083-
layout={**PourbaixDiagramComponent.empty_plot_style}
1084-
),
1094+
self.get_figure_div(),
10851095
False,
10861096
True,
10871097
)
@@ -1103,11 +1113,13 @@ def make_figure(
11031113
conc_dict,
11041114
comp_dict,
11051115
)
1116+
1117+
figure = self.get_figure(
1118+
pourbaix_diagram,
1119+
heatmap_entry=heatmap_entry,
1120+
)
11061121
return (
1107-
self.get_figure(
1108-
pourbaix_diagram,
1109-
heatmap_entry=heatmap_entry,
1110-
),
1122+
self.get_figure_div(figure=figure),
11111123
False,
11121124
False,
11131125
)

0 commit comments

Comments
 (0)