@@ -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