Skip to content

Commit 47df6a3

Browse files
Chiu PeterChiu Peter
authored andcommitted
add invalid comp window and zoom in/out tips
1 parent cafbdd2 commit 47df6a3

File tree

1 file changed

+41
-35
lines changed

1 file changed

+41
-35
lines changed

crystal_toolkit/components/pourbaix.py

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
HEIGHT = 550 # in px
3838
WIDTH = 700 # in px
39-
MIN_CONCENTRATION = 1e-8
39+
MIN_CONCENTRATION = 1e-6
4040
MAX_CONCENTRATION = 5
4141
MIN_PH = -2
4242
MAX_PH = 16
@@ -571,7 +571,7 @@ 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):
574+
def get_figure_div(self, figure=None):
575575
"""
576576
Intentionally update the graph by wrapping it in an `html.Div` instead of directly modifying `go.Figure` or `dcc.Graph`.
577577
This is because, after resetting the axes (e.g., zooming in/out), the updated axes may not match the original ones.
@@ -584,11 +584,17 @@ def get_figure_div(self, figure):
584584
figure = go.Figure(layout={**PourbaixDiagramComponent.empty_plot_style})
585585

586586
return html.Div(
587-
dcc.Graph(
588-
figure=figure,
589-
responsive=True,
590-
config={"displayModeBar": False, "displaylogo": False},
591-
),
587+
[
588+
html.H5(
589+
"💡 Zoom in by selecting an area of interest, and double-click to return to the original view.",
590+
style={"textAlign": "right"},
591+
),
592+
dcc.Graph(
593+
figure=figure,
594+
responsive=True,
595+
config={"displayModeBar": False, "displaylogo": False},
596+
),
597+
]
592598
)
593599

594600
@property
@@ -629,6 +635,7 @@ def _sub_layouts(self) -> dict[str, Component]:
629635
"Update",
630636
id=self.id("comp-btn"),
631637
),
638+
ctl.Block(html.Div(id=self.id("display-composition"))),
632639
html.Br(),
633640
html.Br(),
634641
dcc.Store(id=self.id("elements-store")),
@@ -647,7 +654,6 @@ def _sub_layouts(self) -> dict[str, Component]:
647654
style={"display": "none"},
648655
),
649656
html.Div(id=self.id("element_specific_controls")),
650-
ctl.Block(html.Div(id=self.id("display-composition"))),
651657
]
652658
),
653659
self.get_bool_input(
@@ -694,7 +700,6 @@ def _sub_layouts(self) -> dict[str, Component]:
694700
id=self.id("graph-panel"),
695701
),
696702
)
697-
# html.H5("Zoom in by selecting an area of interest, and double-click to return to the original view.")
698703

699704
return {"graph": graph, "options": options}
700705

@@ -840,7 +845,7 @@ def update_element_specific_sliders(
840845
min=MIN_CONCENTRATION,
841846
max=MAX_CONCENTRATION,
842847
label=f"Concentration of {element} ion",
843-
style={"width": "10rem"},
848+
style={"width": "10rem", "fontSize": "14px"},
844849
)
845850
]
846851
)
@@ -856,7 +861,7 @@ def update_element_specific_sliders(
856861
comp_conc_controls += comp_inputs
857862

858863
ion_label = (
859-
"Set Ion Concentrations"
864+
"Set Ion Concentrations (M)"
860865
if len(elements) > 1
861866
else "Set Ion Concentration"
862867
)
@@ -964,9 +969,8 @@ def update_element_specific_sliders(entries, heatmap_choice, show_heatmap):
964969
external_link = (
965970
f"https://next-gen.materialsproject.org/materials/{mpid_wo_function}"
966971
)
967-
968972
return html.Div(comp_conc_controls), False, external_link
969-
"""
973+
970974
971975
@app.callback(
972976
Output(self.id("display-composition"), "children"),
@@ -997,6 +1001,7 @@ def update_displayed_composition(dependency): # **kwargs):
9971001
)
9981002
9991003
return html.Small(f"Pourbaix composition set to {unicodeify(formula)}.")
1004+
"""
10001005

10011006
@cache.memoize(timeout=5 * 60)
10021007
def get_pourbaix_diagram(pourbaix_entries, **kwargs):
@@ -1006,16 +1011,24 @@ def get_pourbaix_diagram(pourbaix_entries, **kwargs):
10061011
Output(self.id("graph-panel"), "children"),
10071012
Output(self.id("invalid-comp-alarm"), "displayed"),
10081013
Output(self.id("invalid-conc-alarm"), "displayed"),
1014+
Output(self.id("display-composition"), "children"),
10091015
Input(self.id(), "data"),
10101016
Input(self.id("display-composition"), "children"),
10111017
Input(self.get_all_kwargs_id(), "value"),
10121018
Input(self.id("comp-btn"), "n_clicks"),
10131019
State(self.id("elements-store"), "data"),
10141020
State(self.id("comp-text"), "value"),
1021+
Input(self.id("element_specific_controls"), "children"),
10151022
prevent_initial_call=True,
10161023
)
10171024
def make_figure(
1018-
pourbaix_entries, dependency, kwargs, n_clicks, elements, comp_text
1025+
pourbaix_entries,
1026+
dependency,
1027+
kwargs,
1028+
n_clicks,
1029+
elements,
1030+
comp_text,
1031+
dependency2,
10191032
) -> go.Figure:
10201033
# show_heatmap, heatmap_choice, filter_solids
10211034

@@ -1030,27 +1043,26 @@ def make_figure(
10301043

10311044
if len(raw_comp_list) != len(elements):
10321045
logger.error("Invalid composition input!")
1033-
return (
1034-
self.get_figure_div(),
1035-
True,
1036-
False,
1037-
)
1046+
return (self.get_figure_div(), True, False, "")
10381047
try:
10391048
# avoid direct type casting because string inputs may raise errors
10401049
comp_list = [float(t) for t in raw_comp_list]
1050+
comp_dict = {el: comp for comp, el in zip(comp_list, elements)}
1051+
comp = Composition(comp_dict)
1052+
formula = Composition(
1053+
comp.get_integer_formula_and_factor()[0]
1054+
).reduced_formula
1055+
10411056
except Exception:
10421057
logger.error("Invalid composition input!")
1043-
return (
1044-
self.get_figure_div(),
1045-
True,
1046-
False,
1047-
)
1058+
return (self.get_figure_div(), True, False, "")
10481059

10491060
kwargs = self.reconstruct_kwargs_from_state()
10501061

10511062
pourbaix_entries = self.from_data(pourbaix_entries)
10521063

10531064
# Get heatmap id
1065+
heatmap_entry = None
10541066
if kwargs.get("show_heatmap") and kwargs.get("heatmap_choice"):
10551067
# get Entry object based on the heatmap_choice, which is entry_id string
10561068
heatmap_entry = next(
@@ -1065,36 +1077,29 @@ def make_figure(
10651077
for element, coeff in heatmap_entry.composition.items()
10661078
if element not in ELEMENTS_HO
10671079
}
1080+
"""
10681081
else:
10691082
heatmap_entry = None
10701083
10711084
# otherwise, user sets comp_dict
10721085
comp_dict = {}
10731086
# e.g. kwargs contains {"comp-Ag": 0.5, "comp-Fe": 0.5},
10741087
# essentially {slider_name: slider_value}
1075-
"""
1076-
for key, val in kwargs.items():
1077-
if "comp" in key: # keys are encoded like "comp-Ag"
1078-
el = key.split("-")[1]
1079-
comp_dict[el] = val
1080-
"""
1088+
10811089
comp_dict = {}
10821090
for comp_val, element in zip(comp_list, elements):
10831091
comp_dict[element] = comp_val
10841092
10851093
comp_dict = comp_dict or None
1094+
"""
10861095
conc_dict = {}
10871096
# e.g. kwargs contains {"conc-Ag": 1e-6, "conc-Fe": 1e-4},
10881097
# essentially {slider_name: slider_value}
10891098
for key, val in kwargs.items():
10901099
if "conc" in key: # keys are encoded like "conc-Ag"
10911100
if val is None:
10921101
# if the input is out of pre-defined range, Input will get None
1093-
return (
1094-
self.get_figure_div(),
1095-
False,
1096-
True,
1097-
)
1102+
return (self.get_figure_div(), False, True, "")
10981103

10991104
el = key.split("-")[1]
11001105
conc_dict[el] = val
@@ -1122,6 +1127,7 @@ def make_figure(
11221127
self.get_figure_div(figure=figure),
11231128
False,
11241129
False,
1130+
html.Small(f"Pourbaix composition set to {unicodeify(formula)}."),
11251131
)
11261132

11271133
# TODO

0 commit comments

Comments
 (0)