4242MAX_PH = 16
4343MIN_V = - 4
4444MAX_V = 4
45+ PANEL_LINE_HEIGHT = "2em"
4546
4647
4748class PourbaixDiagramComponent (MPComponent ):
@@ -127,6 +128,16 @@ class PourbaixDiagramComponent(MPComponent):
127128 }
128129 )
129130
131+ @staticmethod
132+ def create_centered_object (content ):
133+ return html .Div (
134+ content ,
135+ style = {
136+ "display" : "flex" ,
137+ "justifyContent" : "center" ,
138+ },
139+ )
140+
130141 @staticmethod
131142 def get_figure (
132143 pourbaix_diagram : PourbaixDiagram , heatmap_entry = None , show_water_lines = True
@@ -440,11 +451,10 @@ def _sub_layouts(self) -> dict[str, Component]:
440451 default = self .default_state ["filter_solids" ],
441452 label = "Filter Solids" ,
442453 help_str = "Whether to filter solid phases by stability on the compositional phase diagram. "
443- "The practical consequence of this is that highly oxidized or reduced phases that "
444- "might show up in experiments due to kinetic limitations on oxygen/hydrogen evolution "
445- "won't appear in the diagram, but they are not actually “stable” (and are frequently "
446- "overstabilized from DFT errors). Hence, including only the stable solid phases generally "
447- "leads to the most accurate Pourbaix diagrams." ,
454+ "The practical consequence of this is that we only include materials that are predicted to "
455+ "be thermodynamically stable at RT within the limitations of DFT. Notably, there may be "
456+ "disagreements with experiments e.g., highly oxidized or reduced phases, which are kinetically "
457+ "stabilized through surface passivation." ,
448458 ),
449459 html .Div (
450460 [
@@ -454,23 +464,56 @@ def _sub_layouts(self) -> dict[str, Component]:
454464 id = self .id ("invalid-comp-alarm" ),
455465 message = "Illegal composition entry!" ,
456466 ),
457- html .H5 (
458- "Composition" ,
459- id = self .id ("composition-title" ),
460- style = {"fontWeight" : "bold" },
467+ html .Div (
468+ [
469+ html .H5 (
470+ "Composition Control" ,
471+ style = {
472+ "fontWeight" : "bold" ,
473+ "textAlign" : "center" ,
474+ "flex" : "0 0 100%" ,
475+ },
476+ ),
477+ html .H5 (
478+ "Composition of" ,
479+ id = self .id ("composition-title" ),
480+ # style={"fontWeight": "bold"},
481+ ),
482+ ],
483+ style = {
484+ "line-height" : PANEL_LINE_HEIGHT ,
485+ "display" : "flex" ,
486+ "flexWrap" : "wrap" ,
487+ "justifyContent" : "center" ,
488+ },
461489 ),
462- dcc .Input (
463- id = self .id ("comp-text" ),
464- type = "text" ,
465- # placeholder="composition e.g. 1:1:1",
490+ PourbaixDiagramComponent .create_centered_object (
491+ dcc .Input (
492+ id = self .id ("comp-text" ),
493+ className = "input" ,
494+ type = "text" ,
495+ style = {
496+ "textAlign" : "center" ,
497+ "width" : "10rem" ,
498+ "marginRight" : "0.2rem" ,
499+ "marginBottom" : "0.2rem" ,
500+ "height" : "36px" ,
501+ "fontSize" : "14px" ,
502+ },
503+ ),
466504 ),
467- html .Button (
468- "Update" ,
469- id = self .id ("comp-btn" ),
505+ ctl .Block (
506+ PourbaixDiagramComponent .create_centered_object (
507+ html .Div (
508+ id = self .id ("display-composition" ),
509+ )
510+ )
511+ ),
512+ html .Hr (
513+ style = {
514+ "backgroundColor" : "#C5C5C6" ,
515+ }
470516 ),
471- ctl .Block (html .Div (id = self .id ("display-composition" ))),
472- html .Br (),
473- html .Br (),
474517 dcc .Store (id = self .id ("elements-store" )),
475518 ],
476519 id = self .id ("comp-panel" ),
@@ -486,9 +529,22 @@ def _sub_layouts(self) -> dict[str, Component]:
486529 id = self .id ("conc-panel" ),
487530 style = {"display" : "none" },
488531 ),
489- html .Div (id = self .id ("element_specific_controls" )),
490- ]
532+ html .Div (
533+ id = self .id ("element_specific_controls" ),
534+ ),
535+ PourbaixDiagramComponent .create_centered_object (
536+ html .Button (
537+ "Update" ,
538+ id = self .id ("comp-conc-btn" ),
539+ style = {"display" : "none" },
540+ ),
541+ ),
542+ ],
543+ style = {
544+ "backgroundColor" : "#F1F1F5" ,
545+ },
491546 ),
547+ html .Br (),
492548 self .get_bool_input (
493549 "show_heatmap" , # kwarg_label
494550 # state=self.default_state,
@@ -629,6 +685,8 @@ def update_heatmap_choices(entries, mat_detials, filter_solids):
629685 Output (self .id ("elements-store" ), "data" ),
630686 Output (self .id ("comp-text" ), "value" ),
631687 Output (self .id ("composition-title" ), "children" ),
688+ Output (self .id ("comp-conc-btn" ), "children" ),
689+ Output (self .id ("comp-conc-btn" ), "style" ),
632690 Input (self .id (), "data" ),
633691 prevent_initial_call = True ,
634692 )
@@ -651,57 +709,83 @@ def update_element_specific_sliders(
651709 # exclude O and H
652710 elements = elements - ELEMENTS_HO
653711
654- comp_inputs = []
655712 conc_inputs = []
656713
657714 for element in sorted (elements ):
658- conc_input = html .Div (
659- [
660- self .get_numerical_input (
661- f"conc-{ element } " ,
662- default = 1e-6 ,
663- min = MIN_CONCENTRATION ,
664- max = MAX_CONCENTRATION ,
665- label = f"Concentration of { element } ion" ,
666- style = {"width" : "10rem" , "fontSize" : "14px" },
667- )
668- ]
715+ conc_input = PourbaixDiagramComponent .create_centered_object (
716+ self .get_numerical_input (
717+ f"conc-{ element } " ,
718+ default = 1e-6 ,
719+ min = MIN_CONCENTRATION ,
720+ max = MAX_CONCENTRATION ,
721+ label = f"concentration of { element } ion" ,
722+ style = {
723+ "width" : "10rem" ,
724+ "fontSize" : "14px" ,
725+ },
726+ )
669727 )
670728
671729 conc_inputs .append (conc_input )
672730
673731 comp_conc_controls = []
674- comp_conc_controls += comp_inputs
675732
676733 ion_label = (
677- "Set Ion Concentrations (M) "
734+ "Ion Concentrations Control "
678735 if len (elements ) > 1
679- else "Set Ion Concentration"
736+ else "Ion Concentration Control"
737+ )
738+
739+ comp_conc_controls .append (
740+ html .H5 (
741+ ion_label ,
742+ style = {"fontWeight" : "bold" , "textAlign" : "center" },
743+ ),
744+ )
745+ comp_conc_controls .append (
746+ PourbaixDiagramComponent .create_centered_object (
747+ html .H6 (
748+ f"💡 Set the range between { MIN_CONCENTRATION } and { MAX_CONCENTRATION } (M)"
749+ )
750+ )
680751 )
681- comp_conc_controls .append (ctl .Label (ion_label ))
682752
683753 comp_conc_controls += conc_inputs
684754
685- #
755+ # comp_panel_style
686756 comp_panel_style = {"display" : "none" }
687757 if len (elements ) > 1 :
688- comp_panel_style = {"display" : "block" }
758+ comp_panel_style = {
759+ "display" : "block" ,
760+ }
689761
690- #
762+ # elements store
691763 elements = [element .symbol for element in elements ]
692764
693- #
765+ # default_comp
694766 default_comp = ":" .join (["1" for _ in elements ])
695767
696- #
697- title = "Composition of " + ":" .join (elements )
768+ # composition title
769+ title = "💡 Composition of " + ":" .join (elements )
770+
771+ # update_string
772+ update_string = "Concentration update"
773+ if len (elements ) > 1 :
774+ update_string = "Composition & concentration update"
698775
699776 return (
700- html .Div (comp_conc_controls ),
777+ html .Div (
778+ comp_conc_controls ,
779+ style = {
780+ "line-height" : PANEL_LINE_HEIGHT ,
781+ },
782+ ),
701783 comp_panel_style ,
702784 elements ,
703785 default_comp ,
704786 title ,
787+ update_string ,
788+ {"display" : "block" , "height" : "36px" },
705789 )
706790
707791 @cache .memoize (timeout = 5 * 60 )
@@ -715,26 +799,32 @@ def get_pourbaix_diagram(pourbaix_entries, **kwargs):
715799 Output (self .id ("display-composition" ), "children" ),
716800 Input (self .id (), "data" ),
717801 Input (self .id ("display-composition" ), "children" ),
718- Input (self .get_all_kwargs_id (), "value" ),
719- Input (self .id ("comp-btn" ), "n_clicks" ),
802+ State (self .get_all_kwargs_id (), "value" ),
803+ Input (self .id ("comp-conc- btn" ), "n_clicks" ),
720804 State (self .id ("elements-store" ), "data" ),
721805 State (self .id ("comp-text" ), "value" ),
722806 Input (self .id ("element_specific_controls" ), "children" ),
807+ Input (self .get_kwarg_id ("filter_solids" ), "value" ),
808+ Input (self .get_kwarg_id ("show_heatmap" ), "value" ),
809+ Input (self .get_kwarg_id ("heatmap_choice" ), "value" ),
723810 prevent_initial_call = True ,
724811 )
725812 def make_figure (
726813 pourbaix_entries ,
727- dependency ,
814+ display_composition ,
728815 kwargs ,
729816 n_clicks ,
730817 elements ,
731818 comp_text ,
732- dependency2 ,
819+ element_specific_controls ,
820+ filter_solids ,
821+ show_heatmap ,
822+ heatmap_choice ,
733823 ) -> go .Figure :
734824 if pourbaix_entries is None :
735825 raise PreventUpdate
736826
737- # check if composition input
827+ # Only update
738828 if n_clicks :
739829 raw_comp_list = comp_text .split (":" )
740830 else :
@@ -808,6 +898,7 @@ def make_figure(
808898 pourbaix_diagram ,
809899 heatmap_entry = heatmap_entry ,
810900 )
901+
811902 return (
812903 self .get_figure_div (figure = figure ),
813904 False ,
0 commit comments