From 37231de1ecd13c1deb70ff19d84df5b373a6893f Mon Sep 17 00:00:00 2001
From: Andres Ortega-Guerrero
<34098967+AndresOrtegaGuerrero@users.noreply.github.com>
Date: Tue, 14 Jan 2025 23:01:42 +0100
Subject: [PATCH] Adding widget to control aspect ratio of plot (#1098)
* Adding sliders to control the width of the plot
* When plot_type has bands+pdos there is a widget to control the width of the subplots
---
.../common/bands_pdos/bandpdoswidget.py | 55 +++++++++++++++++++
src/aiidalab_qe/common/bands_pdos/model.py | 19 +++++++
2 files changed, 74 insertions(+)
diff --git a/src/aiidalab_qe/common/bands_pdos/bandpdoswidget.py b/src/aiidalab_qe/common/bands_pdos/bandpdoswidget.py
index 3683a44e5..61d9af4eb 100644
--- a/src/aiidalab_qe/common/bands_pdos/bandpdoswidget.py
+++ b/src/aiidalab_qe/common/bands_pdos/bandpdoswidget.py
@@ -235,6 +235,49 @@ def render(self):
"value",
)
+ # Aspect ratio
+ self.horizontal_width_percentage = ipw.IntSlider(
+ min=30,
+ max=100,
+ step=5,
+ description="Horizonal width %:",
+ orientation="horizontal",
+ continuous_update=False,
+ readout=True,
+ readout_format=".0f",
+ style={"description_width": "initial"},
+ layout=ipw.Layout(width="380px"),
+ )
+ ipw.link(
+ (self._model, "horizontal_width_percentage"),
+ (self.horizontal_width_percentage, "value"),
+ )
+ self.horizontal_width_percentage.observe(
+ self._on_horizontal_width_change,
+ "value",
+ )
+
+ self.bands_width_percentage = ipw.IntSlider(
+ min=10,
+ max=90,
+ step=5,
+ description="Bands width %:",
+ orientation="horizontal",
+ continuous_update=False,
+ readout=True,
+ readout_format=".0f",
+ style={"description_width": "initial"},
+ layout=ipw.Layout(width="380px"),
+ )
+ ipw.link(
+ (self._model, "bands_width_percentage"),
+ (self.bands_width_percentage, "value"),
+ )
+ self.bands_width_percentage.observe(
+ self._on_bands_width_change,
+ "value",
+ )
+
self.legend_interaction_description = ipw.HTML(
"""
@@ -289,7 +332,13 @@ def _initial_plot(self):
layout=ipw.Layout(margin="0 auto"),
),
self.color_selector,
+ self.horizontal_width_percentage,
]
+ if self._model.helper.plot_type == "combined":
+ self.children = [
+ *self.children,
+ self.bands_width_percentage,
+ ]
def _update_bands_projections(self, _):
"""Update the plot with the selected projection."""
@@ -352,3 +401,9 @@ def _trace_selector_change(self, change):
def _update_trace_color(self, change):
self._model.update_trace_color(change["new"])
+
+ def _on_horizontal_width_change(self, change):
+ self._model.update_horizontal_width(change["new"])
+
+ def _on_bands_width_change(self, change):
+ self._model.update_column_width_ratio(change["new"])
diff --git a/src/aiidalab_qe/common/bands_pdos/model.py b/src/aiidalab_qe/common/bands_pdos/model.py
index 2439bcca2..60fa7e1cd 100644
--- a/src/aiidalab_qe/common/bands_pdos/model.py
+++ b/src/aiidalab_qe/common/bands_pdos/model.py
@@ -71,6 +71,12 @@ class BandsPdosModel(Model):
)
image_format = tl.Unicode("png")
+ # Aspect ratio
+ horizontal_width = 850 # pixels
+ horizontal_width_percentage = tl.Int(100)
+
+ bands_width_percentage = tl.Int(70)
+
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -290,6 +296,19 @@ def update_trace_color(self, color):
# Update the color picker to match the updated trace
self.color_picker = rgba_to_hex(self.plot.data[self.trace].line.color)
+ def update_horizontal_width(self, width_percentage):
+ """Update the horizontal width based on the percentge."""
+ horizontal_width = int((width_percentage / 100) * self.horizontal_width)
+ self.plot.layout.width = horizontal_width
+
+ def update_column_width_ratio(self, bands_width_percentage):
+ """Update the combined_column_widths of the combined plot based on percentage."""
+ bands_width = bands_width_percentage / 100
+ self.plot.update_layout(
+ xaxis={"domain": [0, bands_width - 0.004]},
+ xaxis2={"domain": [bands_width + 0.004, 1]},
+ )
+
def download_image(self, _=None):
"""
Downloads the current plot as an image in the format specified by self.image_format.