@@ -127,173 +127,6 @@ class PourbaixDiagramComponent(MPComponent):
127127 }
128128 )
129129
130- # @staticmethod
131- # def get_figure_with_shapes(
132- # pourbaix_diagram, heatmap_entry=None, heatmap_as_contour=True, show_labels=True
133- # ):
134- # """
135- # Deprecated. This method returns a figure with Pourbaix domains as "shapes" and labels
136- # as "annotations." The new figure method instead returns a Pourbaix diagram with
137- # domains and labels as independent traces, so that they can be interacted with and
138- # placed on a legend.
139- #
140- # Static method for getting plotly figure from a Pourbaix diagram.
141- #
142- # Args:
143- # pourbaix_diagram (PourbaixDiagram): Pourbaix diagram to plot
144- # heatmap_entry (PourbaixEntry): id for the heatmap generation
145- # heatmap_as_contour (bool): if True, display contours, if False heatmap as grid
146- #
147- # Returns:
148- # (dict) figure layout
149- #
150- # """
151- # # TODO: fix mpid problem. Can't attach from mpid without it being a structure.
152- # data = []
153- #
154- # # Get data for heatmap
155- # if heatmap_entry is not None:
156- # ph_range = np.arange(-2, 16.001, 0.1)
157- # v_range = np.arange(-2, 4.001, 0.1)
158- # ph_mesh, v_mesh = np.meshgrid(ph_range, v_range)
159- # decomposition_e = pourbaix_diagram.get_decomposition_energy(
160- # heatmap_entry, ph_mesh, v_mesh
161- # )
162- #
163- # # Generate hoverinfo
164- # hovertexts = []
165- # for ph_val, v_val, de_val in zip(
166- # ph_mesh.ravel(), v_mesh.ravel(), decomposition_e.ravel()
167- # ):
168- # hovertext = [
169- # f"∆G<sub>pbx</sub>={de_val:.2f}",
170- # f"ph={ph_val:.2f}",
171- # f"V={v_val:.2f}",
172- # ]
173- # hovertext = "<br>".join(hovertext)
174- # hovertexts.append(hovertext)
175- # hovertexts = np.reshape(hovertexts, list(decomposition_e.shape))
176- #
177- # # Enforce decomposition limit energy
178- # decomposition_e = np.min(
179- # [decomposition_e, np.ones(decomposition_e.shape)], axis=0
180- # )
181- #
182- # if not heatmap_as_contour:
183- # # Plotly needs a list here for validation
184- # h_map = go.Heatmap(
185- # x=list(ph_range),
186- # y=list(v_range),
187- # z=decomposition_e,
188- # text=hovertexts,
189- # hoverinfo="text",
190- # colorbar={
191- # "title": "∆G<sub>pbx</sub> (eV/atom)",
192- # "titleside": "right",
193- # },
194- # colorscale=PourbaixDiagramComponent.colorscale,
195- # zmin=0,
196- # zmax=1,
197- # )
198- # data.append(h_map)
199- #
200- # else:
201- #
202- # h_map = go.Contour(
203- # z=decomposition_e,
204- # x=list(ph_range),
205- # y=list(v_range),
206- # colorscale=PourbaixDiagramComponent.colorscale, # or magma
207- # zmin=0,
208- # zmax=1,
209- # connectgaps=True,
210- # line_smoothing=0,
211- # line_width=0,
212- # contours_coloring="heatmap",
213- # text=hovertexts,
214- # )
215- # data.insert(0, h_map)
216- #
217- # shapes = []
218- # xy_data = []
219- # labels = []
220- #
221- # for entry, vertices in pourbaix_diagram._stable_domain_vertices.items():
222- # formula = entry.name
223- # clean_formula = PourbaixDiagramComponent.clean_formula(formula)
224- #
225- # # Generate annotation
226- # xy_data.append(np.average(vertices, axis=0))
227- # labels.append(clean_formula)
228- #
229- # # Info on SVG paths: https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
230- # # Move to first point
231- # path = "M {},{}".format(*vertices[0])
232- # # Draw lines to each other point
233- # path += "".join("L {},{}".format(*vertex) for vertex in vertices[1:])
234- # # Close path
235- # path += "Z"
236- #
237- # # Note that the lines and fills are added separately
238- # # so that the lines but not the fills will show up on heatmap.
239- # # This may be condensable in the future if plotly adds a more
240- # # general z-ordering of objects
241- #
242- # # Fill with turquoise if solution
243- # if heatmap_entry is None:
244- # fillcolor = "White" if "Ion" in entry.phase_type else "PaleTurquoise"
245- # shape = go.layout.Shape(
246- # type="path",
247- # path=path,
248- # fillcolor=fillcolor,
249- # layer="below",
250- # )
251- # shapes.append(shape)
252- #
253- # # Add lines separately so they show up on heatmap
254- # shape = go.layout.Shape(
255- # type="path",
256- # path=path,
257- # fillcolor="rgba(0,0,0,0)",
258- # line={"color": "Black", "width": 1},
259- # )
260- # shapes.append(shape)
261- #
262- # layout = {**PourbaixDiagramComponent.default_plot_style}
263- # layout.update({"shapes": shapes})
264- #
265- # if show_labels:
266- # if len(pourbaix_diagram.pbx_elts) == 1:
267- # # Add annotations to layout
268- # annotations = [
269- # {
270- # "align": "center",
271- # "font": {"color": "#000000", "size": 15.0},
272- # "opacity": 1,
273- # "showarrow": False,
274- # "text": label,
275- # "x": x,
276- # "xanchor": "center",
277- # "yanchor": "auto",
278- # # "xshift": -10,
279- # # "yshift": -10,
280- # "xref": "x",
281- # "y": y,
282- # "yref": "y",
283- # }
284- # for (x, y), label in zip(xy_data, labels)
285- # ]
286- # layout.update({"annotations": annotations})
287- # else:
288- # x, y = zip(*xy_data)
289- # data.append(
290- # go.Scatter(x=x, y=y, text=labels, hoverinfo="text", mode="markers")
291- # )
292- #
293- # figure = go.Figure(data=data, layout=layout)
294- #
295- # return figure
296-
297130 @staticmethod
298131 def get_figure (
299132 pourbaix_diagram : PourbaixDiagram , heatmap_entry = None , show_water_lines = True
@@ -820,23 +653,8 @@ def update_element_specific_sliders(
820653
821654 comp_inputs = []
822655 conc_inputs = []
823- for element in sorted (elements ):
824- if len (elements ) > 1 :
825- """
826- comp_input = html.Div(
827- [
828- self.get_slider_input(
829- f"comp-{element}",
830- default=comp_defaults[element],
831- label=f"Composition of {element}",
832- domain=[0, 1],
833- step=0.01,
834- )
835- ]
836- )
837- comp_inputs.append(comp_input)
838- """
839656
657+ for element in sorted (elements ):
840658 conc_input = html .Div (
841659 [
842660 self .get_numerical_input (
@@ -853,11 +671,6 @@ def update_element_specific_sliders(
853671 conc_inputs .append (conc_input )
854672
855673 comp_conc_controls = []
856- # comp_conc_controls.append(
857- # ctl.Block(html.Div(id=self.id("display-composition")))
858- # )
859- # if comp_inputs and (not show_heatmap) and (not heatmap_entry):
860- # comp_conc_controls += comp_inputs
861674 comp_conc_controls += comp_inputs
862675
863676 ion_label = (
@@ -870,7 +683,9 @@ def update_element_specific_sliders(
870683 comp_conc_controls += conc_inputs
871684
872685 #
873- comp_panel_style = {"display" : "block" }
686+ comp_panel_style = {"display" : "none" }
687+ if len (elements ) > 1 :
688+ comp_panel_style = {"display" : "block" }
874689
875690 #
876691 elements = [element .symbol for element in elements ]
@@ -889,120 +704,6 @@ def update_element_specific_sliders(
889704 title ,
890705 )
891706
892- """
893- @app.callback(
894- Output(self.id("element_specific_controls"), "children"),
895- Output(self.id("ext-link"), "hidden"),
896- Output(self.id("ext-link"), "href"),
897- Input(self.id(), "data"),
898- Input(self.get_kwarg_id("heatmap_choice"), "value"),
899- State(self.get_kwarg_id("show_heatmap"), "value"),
900- prevent_initial_call=True,
901- )
902- def update_element_specific_sliders(entries, heatmap_choice, show_heatmap):
903- if (not entries) or (not heatmap_choice[0]):
904- raise PreventUpdate
905-
906- elements = set()
907-
908- kwargs = self.reconstruct_kwargs_from_state()
909- heatmap_choice = kwargs.get("heatmap_choice")
910- show_heatmap = kwargs.get("show_heatmap")
911- heatmap_entry = None
912-
913- for entry in entries:
914- if entry["entry_id"].startswith("mp"):
915- composition = Composition(entry["entry"]["composition"])
916- elements.update(composition.elements)
917- if entry["entry_id"] == heatmap_choice:
918- heatmap_entry = entry
919-
920- # exclude O and H
921- elements = elements - ELEMENTS_HO
922-
923- comp_defaults = {element: 1 / len(elements) for element in elements}
924-
925- comp_inputs = []
926- conc_inputs = []
927- for element in sorted(elements):
928- if len(elements) > 1:
929- comp_input = html.Div(
930- [
931- self.get_slider_input(
932- f"comp-{element}",
933- default=comp_defaults[element],
934- label=f"Composition of {element}",
935- domain=[0, 1],
936- step=0.01,
937- )
938- ]
939- )
940- comp_inputs.append(comp_input)
941-
942- conc_input = html.Div(
943- [
944- self.get_numerical_input(
945- f"conc-{element}",
946- default=1e-6,
947- label=f"Concentration of {element} ion",
948- style={"width": "10rem"},
949- )
950- ]
951- )
952-
953- conc_inputs.append(conc_input)
954-
955- comp_conc_controls = []
956- if comp_inputs and (not show_heatmap) and (not heatmap_entry):
957- comp_conc_controls += comp_inputs
958- comp_conc_controls.append(
959- ctl.Block(html.Div(id=self.id("display-composition")))
960- )
961- if len(elements) > 1:
962- comp_conc_controls.append(ctl.Label("Set Ion Concentrations"))
963- else:
964- comp_conc_controls.append(ctl.Label("Set Ion Concentration"))
965- comp_conc_controls += conc_inputs
966-
967- # external link to detail page
968- mpid_wo_function = "mp-" + heatmap_choice.split("-")[1]
969- external_link = (
970- f"https://next-gen.materialsproject.org/materials/{mpid_wo_function}"
971- )
972- return html.Div(comp_conc_controls), False, external_link
973-
974-
975- @app.callback(
976- Output(self.id("display-composition"), "children"),
977- Input(self.id("element_specific_controls"), "children"),
978- prevent_initial_call=True,
979- # Input(self.get_all_kwargs_id(), "value"),
980- )
981- def update_displayed_composition(dependency): # **kwargs):
982- kwargs = self.reconstruct_kwargs_from_state()
983-
984- comp_dict = {}
985- for key, val in kwargs.items():
986- if "comp" in key: # keys are encoded like "comp-Ag"
987- el = key.split("-")[1]
988- comp_dict[el] = val
989- comp_dict = comp_dict or None
990- if not comp_dict:
991- return ""
992-
993- try:
994- comp = Composition(comp_dict)
995- formula = Composition(
996- comp.get_integer_formula_and_factor()[0]
997- ).reduced_formula
998- except Exception:
999- return html.Small(
1000- "Invalid composition selected.", style={"color": "red"}
1001- )
1002-
1003- return html.Small(f"Pourbaix composition set to {unicodeify(formula)}.")
1004- """
1005-
1006707 @cache .memoize (timeout = 5 * 60 )
1007708 def get_pourbaix_diagram (pourbaix_entries , ** kwargs ):
1008709 return PourbaixDiagram (pourbaix_entries , ** kwargs )
@@ -1030,8 +731,6 @@ def make_figure(
1030731 comp_text ,
1031732 dependency2 ,
1032733 ) -> go .Figure :
1033- # show_heatmap, heatmap_choice, filter_solids
1034-
1035734 if pourbaix_entries is None :
1036735 raise PreventUpdate
1037736
@@ -1077,21 +776,7 @@ def make_figure(
1077776 for element , coeff in heatmap_entry .composition .items ()
1078777 if element not in ELEMENTS_HO
1079778 }
1080- """
1081- else:
1082- heatmap_entry = None
1083-
1084- # otherwise, user sets comp_dict
1085- comp_dict = {}
1086- # e.g. kwargs contains {"comp-Ag": 0.5, "comp-Fe": 0.5},
1087- # essentially {slider_name: slider_value}
1088-
1089- comp_dict = {}
1090- for comp_val, element in zip(comp_list, elements):
1091- comp_dict[element] = comp_val
1092779
1093- comp_dict = comp_dict or None
1094- """
1095780 conc_dict = {}
1096781 # e.g. kwargs contains {"conc-Ag": 1e-6, "conc-Fe": 1e-4},
1097782 # essentially {slider_name: slider_value}
@@ -1129,7 +814,3 @@ def make_figure(
1129814 False ,
1130815 html .Small (f"Pourbaix composition set to { unicodeify (formula )} ." ),
1131816 )
1132-
1133- # TODO
1134- # def graph_layout(self):
1135- # return self._sub_layouts["graph"]
0 commit comments