From 2016505b051e79f371f6b8d43bf21584a6806e49 Mon Sep 17 00:00:00 2001 From: "peter810601@gmail.com" Date: Tue, 30 Dec 2025 11:40:03 -0800 Subject: [PATCH 1/4] add persistence across session and responsive layout --- crystal_toolkit/components/phonon.py | 84 +++++++++++++++++++++------- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/crystal_toolkit/components/phonon.py b/crystal_toolkit/components/phonon.py index 5ef76d90..628106b6 100644 --- a/crystal_toolkit/components/phonon.py +++ b/crystal_toolkit/components/phonon.py @@ -26,6 +26,8 @@ from crystal_toolkit.helpers.layouts import Column, Columns, Label, get_data_list from crystal_toolkit.helpers.pretty_labels import pretty_labels +import json + if TYPE_CHECKING: from pymatgen.electronic_structure.bandstructure import BandStructureSymmLine from pymatgen.electronic_structure.dos import CompleteDos @@ -37,6 +39,16 @@ MAX_MAGNITUDE = 300 MIN_MAGNITUDE = 0 +class NumpyEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, np.ndarray): + return obj.tolist() + if isinstance(obj, np.integer): + return int(obj) + if isinstance(obj, np.floating): + return float(obj) + return super().default(obj) + # TODOs: # - look for additional projection methods in phonon DOS (currently only atom # projections supported) @@ -80,12 +92,18 @@ def _sub_layouts(self) -> dict[str, Component]: fig = PhononBandstructureAndDosComponent.get_figure(None, None) # Main plot - graph = dcc.Graph( - figure=fig, - config={"displayModeBar": False}, - responsive=False, - id=self.id("ph-bsdos-graph"), + graph = html.Div( + [ + dcc.Graph( + figure=fig, + config={"displayModeBar": False}, + responsive=True, + id=self.id("ph-bsdos-graph"), + style={"height": "520px"} + ) + ] ) + # Brillouin zone zone_scene = self.get_brillouin_zone_scene(None) @@ -153,12 +171,24 @@ def _sub_layouts(self) -> dict[str, Component]: summary_dict = self._get_data_list_dict(None, None) summary_table = get_data_list(summary_dict) - # crystal visualization - - tip = html.H5( - "💡 Tips: Click different q-points and bands in the dispersion diagram to see the crystal vibration!", + tip = html.Div( + html.Span( + "💡 Tips: Click different q-points and bands in the dispersion diagram to see the crystal vibration!", + style={ + "border": "0.5px dashed black", + "display": "inline-flex", + "alignItems": "center", + "justifyContent": "center", + "textAlign": "center", + } + ), + style={ + "display": "flex", + "justifyContent": "center", + } ) - + + # crystal visualization crystal_animation = html.Div( CrystalToolkitAnimationScene( data={}, @@ -167,16 +197,16 @@ def _sub_layouts(self) -> dict[str, Component]: settings={"defaultZoom": 1.2}, axisView="SW", showControls=False, # disable download for now - ), - style={"width": "60%"}, + ) ) crystal_animation_controls = html.Div( [ html.Br(), - html.Div(tip, style={"textAlign": "center"}), + html.Br(), html.Br(), html.H5("Control Panel", style={"textAlign": "center"}), + html.Br(), html.H6("Supercell modification"), html.Br(), html.Div( @@ -184,6 +214,7 @@ def _sub_layouts(self) -> dict[str, Component]: self.get_numerical_input( kwarg_label="scale-x", default=1, + persistence_type="session", is_int=True, label="x", min=1, @@ -192,6 +223,7 @@ def _sub_layouts(self) -> dict[str, Component]: self.get_numerical_input( kwarg_label="scale-y", default=1, + persistence_type="session", is_int=True, label="y", min=1, @@ -200,18 +232,28 @@ def _sub_layouts(self) -> dict[str, Component]: self.get_numerical_input( kwarg_label="scale-z", default=1, + persistence_type="session", is_int=True, label="z", min=1, style={"width": "5rem"}, ), - html.Button( - "Update", - id=self.id("supercell-controls-btn"), - style={"height": "40px"}, - ), + html.Div( + html.Button( + "Update", + id=self.id("supercell-controls-btn"), + style={"height": "40px"}, + ), + style={ + "textAlign": "center", + "width": "100%" + } + ) + ], - style={"display": "flex"}, + style={ + "display": "flex" + }, ), html.Br(), html.Div( @@ -224,6 +266,7 @@ def _sub_layouts(self) -> dict[str, Component]: ) ), ], + style={"width": "100%"} ) return { @@ -244,6 +287,7 @@ def _get_animation_panel(self): [ Column( [ + sub_layouts["tip"], Columns( [ sub_layouts["crystal-animation"], @@ -252,7 +296,7 @@ def _get_animation_panel(self): ) ] ), - ] + ], ) def layout(self) -> html.Div: From 60bbdedb18159855a0502956e6de48b6b1639e0c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Dec 2025 19:44:39 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- crystal_toolkit/components/phonon.py | 32 +++++++++++----------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/crystal_toolkit/components/phonon.py b/crystal_toolkit/components/phonon.py index 628106b6..99e87841 100644 --- a/crystal_toolkit/components/phonon.py +++ b/crystal_toolkit/components/phonon.py @@ -1,6 +1,7 @@ from __future__ import annotations import itertools +import json from copy import deepcopy from typing import TYPE_CHECKING, Any @@ -26,8 +27,6 @@ from crystal_toolkit.helpers.layouts import Column, Columns, Label, get_data_list from crystal_toolkit.helpers.pretty_labels import pretty_labels -import json - if TYPE_CHECKING: from pymatgen.electronic_structure.bandstructure import BandStructureSymmLine from pymatgen.electronic_structure.dos import CompleteDos @@ -39,6 +38,7 @@ MAX_MAGNITUDE = 300 MIN_MAGNITUDE = 0 + class NumpyEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, np.ndarray): @@ -49,6 +49,7 @@ def default(self, obj): return float(obj) return super().default(obj) + # TODOs: # - look for additional projection methods in phonon DOS (currently only atom # projections supported) @@ -99,11 +100,10 @@ def _sub_layouts(self) -> dict[str, Component]: config={"displayModeBar": False}, responsive=True, id=self.id("ph-bsdos-graph"), - style={"height": "520px"} + style={"height": "520px"}, ) ] ) - # Brillouin zone zone_scene = self.get_brillouin_zone_scene(None) @@ -180,14 +180,14 @@ def _sub_layouts(self) -> dict[str, Component]: "alignItems": "center", "justifyContent": "center", "textAlign": "center", - } - ), + }, + ), style={ "display": "flex", "justifyContent": "center", - } + }, ) - + # crystal visualization crystal_animation = html.Div( CrystalToolkitAnimationScene( @@ -244,16 +244,10 @@ def _sub_layouts(self) -> dict[str, Component]: id=self.id("supercell-controls-btn"), style={"height": "40px"}, ), - style={ - "textAlign": "center", - "width": "100%" - } - ) - + style={"textAlign": "center", "width": "100%"}, + ), ], - style={ - "display": "flex" - }, + style={"display": "flex"}, ), html.Br(), html.Div( @@ -266,7 +260,7 @@ def _sub_layouts(self) -> dict[str, Component]: ) ), ], - style={"width": "100%"} + style={"width": "100%"}, ) return { @@ -293,7 +287,7 @@ def _get_animation_panel(self): sub_layouts["crystal-animation"], sub_layouts["crystal-animation-controls"], ] - ) + ), ] ), ], From 302e60c0a2b7db642042b6c35cd074468d0d0c4d Mon Sep 17 00:00:00 2001 From: "peter810601@gmail.com" Date: Tue, 30 Dec 2025 11:45:13 -0800 Subject: [PATCH 3/4] remove debug object --- crystal_toolkit/components/phonon.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/crystal_toolkit/components/phonon.py b/crystal_toolkit/components/phonon.py index 628106b6..0adda7d5 100644 --- a/crystal_toolkit/components/phonon.py +++ b/crystal_toolkit/components/phonon.py @@ -39,16 +39,6 @@ MAX_MAGNITUDE = 300 MIN_MAGNITUDE = 0 -class NumpyEncoder(json.JSONEncoder): - def default(self, obj): - if isinstance(obj, np.ndarray): - return obj.tolist() - if isinstance(obj, np.integer): - return int(obj) - if isinstance(obj, np.floating): - return float(obj) - return super().default(obj) - # TODOs: # - look for additional projection methods in phonon DOS (currently only atom # projections supported) From 50f2485abfab586fe6947426aaed93c6c3c75fcb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Dec 2025 22:53:15 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- crystal_toolkit/components/phonon.py | 1 - 1 file changed, 1 deletion(-) diff --git a/crystal_toolkit/components/phonon.py b/crystal_toolkit/components/phonon.py index 8e6350d9..7a3ed5f5 100644 --- a/crystal_toolkit/components/phonon.py +++ b/crystal_toolkit/components/phonon.py @@ -1,7 +1,6 @@ from __future__ import annotations import itertools -import json from copy import deepcopy from typing import TYPE_CHECKING, Any