From 32f1241e457c01aee57819924cec21fda10cdf93 Mon Sep 17 00:00:00 2001 From: Edan Bainglass Date: Wed, 6 May 2026 16:06:25 +0000 Subject: [PATCH 1/4] Set `compute_fermi_surface` in `set_model_state` --- src/aiidalab_qe_wannier90/model.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aiidalab_qe_wannier90/model.py b/src/aiidalab_qe_wannier90/model.py index e75853a..bb50a1b 100644 --- a/src/aiidalab_qe_wannier90/model.py +++ b/src/aiidalab_qe_wannier90/model.py @@ -84,6 +84,7 @@ def set_model_state(self, parameters: dict): self.plot_wannier_functions = parameters.get('plot_wannier_functions', False) self.number_of_disproj_max = parameters.get('number_of_disproj_max', 15) self.number_of_disproj_min = parameters.get('number_of_disproj_min', 2) + self.compute_fermi_surface = parameters.get('compute_fermi_surface', False) self.compute_dhva_frequencies = parameters.get('compute_dhva_frequencies', False) self.dhva_ending_phi = parameters.get('dHvA_frequencies_parameters', {}).get('ending_phi', 90.0) self.dhva_ending_theta = parameters.get('dHvA_frequencies_parameters', {}).get('ending_theta', 90.0) From b9874f87c0505b3b9c8a02d33aeaf34b3ca7a20a Mon Sep 17 00:00:00 2001 From: Edan Bainglass Date: Wed, 6 May 2026 16:06:34 +0000 Subject: [PATCH 2/4] Fix UI --- src/aiidalab_qe_wannier90/setting.py | 153 +++++++++++++-------------- 1 file changed, 74 insertions(+), 79 deletions(-) diff --git a/src/aiidalab_qe_wannier90/setting.py b/src/aiidalab_qe_wannier90/setting.py index 68dfdb0..9120c80 100644 --- a/src/aiidalab_qe_wannier90/setting.py +++ b/src/aiidalab_qe_wannier90/setting.py @@ -12,14 +12,29 @@ class ConfigurationSettingPanel( def __init__(self, model: ConfigurationSettingsModel, **kwargs): super().__init__(model, **kwargs) - # Initialize attributes to avoid AttributeError - self.compute_fermi_surface = None - self.params_fermi_surface_vbox = ipw.VBox([]) - self.params_dhva_freqs_vbox = ipw.VBox([]) + self._model.observe( + self._on_electronic_type_change, + 'electronic_type', + ) + self._model.observe( + self._on_compute_fermi_surface_change, + 'compute_fermi_surface', + ) + self._model.observe( + self._on_compute_dhva_freqs_change, + 'compute_dhva_frequencies', + ) + self._model.observe( + self._on_frozen_type_change, + 'frozen_type', + ) + + def render(self): + if self.rendered: + return - # error message self.error_message = ipw.HTML() - # Warning message + self.warning_message = ipw.HTML( """
⚠️ This plugin requires the Wannier90 code from the latest source code from the @@ -38,24 +53,6 @@ def __init__(self, model: ConfigurationSettingsModel, **kwargs):
""" ) - self._model.observe( - self._on_electronic_type_change, - 'electronic_type', - ) - self._model.observe( - self._on_compute_fermi_surface_change, - 'compute_fermi_surface', - ) - self._model.observe( - self._on_compute_dhva_freqs_change, - 'compute_dhva_frequencies', - ) - - def render(self): - - if self.rendered: - return - # Workflow explanation workflow_explanation = ipw.HTML( """
@@ -70,7 +67,6 @@ def render(self):
""" ) - checkbox_layout = ipw.Layout(width='fit-content', margin='4px 2px') self.exclude_semicore = ipw.Checkbox( value=self._model.exclude_semicore, @@ -106,8 +102,8 @@ def render(self): value=self._model.scan_pdwf_parameter, description='Optimize PDWF thresholds', indent=False, - tooltip='If enabled, an exhaustive scan of the PDWF thresholds is ' \ - 'performed (up to 30 Wannierizations) to find those that bring the ' \ + tooltip='If enabled, an exhaustive scan of the PDWF thresholds is ' + 'performed (up to 30 Wannierizations) to find those that bring the ' 'bands distance (for bands up to 2 eV above the Fermi level) below 10 meV.', ) ipw.link( @@ -125,7 +121,7 @@ def render(self): (self.plot_wannier_functions, 'value'), ) self.compute_fermi_surface = ipw.Checkbox( - value = self._model.compute_fermi_surface, + value=self._model.compute_fermi_surface, description='Compute Fermi surface', indent=False, layout=checkbox_layout, @@ -156,11 +152,8 @@ def render(self): (self._model, 'compute_dhva_frequencies'), (self.compute_dhva_frequencies, 'value'), ) - self.params_fermi_surface_vbox = ipw.VBox([]) - self.params_dhva_freqs_vbox = ipw.VBox( - [], - layout=ipw.Layout(margin='0 0 0 40px'), - ) + self.params_fermi_surface_vbox = ipw.VBox() + self.params_dhva_freqs_vbox = ipw.VBox(layout=ipw.Layout(margin='0 0 0 40px')) self.dhva_starting_phi = ipw.FloatText( value=self._model.dhva_starting_phi, @@ -220,19 +213,23 @@ def render(self): ) # Assemble rows - self.dhva_first_row = ipw.HBox([ - ipw.Label('Starting magnetic field orientation:', layout=ipw.Layout(width='200px')), - self.dhva_starting_phi, - self.dhva_starting_theta, - self.dhva_starting_label - ]) + self.dhva_first_row = ipw.HBox( + [ + ipw.Label('Starting magnetic field orientation:', layout=ipw.Layout(width='200px')), + self.dhva_starting_phi, + self.dhva_starting_theta, + self.dhva_starting_label, + ] + ) - self.dhva_second_row = ipw.HBox([ - ipw.Label('Final magnetic field orientation:', layout=ipw.Layout(width='200px')), - self.dhva_ending_phi, - self.dhva_ending_theta, - self.dhva_ending_label - ]) + self.dhva_second_row = ipw.HBox( + [ + ipw.Label('Final magnetic field orientation:', layout=ipw.Layout(width='200px')), + self.dhva_ending_phi, + self.dhva_ending_theta, + self.dhva_ending_label, + ] + ) self.dhva_third_row = ipw.IntText( value=self._model.dhva_num_rotation, description='Number of rotation steps', @@ -274,7 +271,6 @@ def render(self): """ ) - # Dropdown for Projection Type self.projection_type = ipw.Dropdown( options=[ @@ -291,7 +287,6 @@ def render(self): layout=ipw.Layout(width='700px'), ) - ipw.link( (self._model, 'projection_type'), (self.projection_type, 'value'), @@ -325,6 +320,10 @@ def render(self): style={'description_width': 'initial'}, layout=ipw.Layout(width='500px'), ) + ipw.link( + (self._model, 'frozen_type'), + (self.frozen_type, 'value'), + ) # Energy Window Input (default 2 eV) self.energy_window_label = ipw.HTML( @@ -338,17 +337,17 @@ def render(self): layout=ipw.Layout(width='90px'), ) self.energy_window_widget = ipw.HBox( - children=[self.energy_window_label, self.energy_window_input], - layout=ipw.Layout(width='100%', align_items='center', overflow='visible'), + children=[ + self.energy_window_label, + self.energy_window_input, + ], + layout=ipw.Layout( + width='100%', + align_items='center', + overflow='visible', + ), ) - # Attach the event listener - self.frozen_type.observe(self._update_energy_window_visibility, names='value') - - # Initialize visibility - self._update_energy_window_visibility({'new': self.frozen_type.value}) - - # Layout the widgets self.frozen_states_widget = ipw.VBox( [ self.description_html, @@ -357,17 +356,7 @@ def render(self): ], layout=ipw.Layout(width='100%', align_items='flex-start', overflow='visible'), ) - self.frozen_type = ipw.Dropdown( - options=['fixed_plus_projectability', 'projectability', 'energy_fixed'], - value=self._model.frozen_type, - description='Frozen states:', - style={'description_width': 'initial'}, - ) - ipw.link( - (self._model, 'frozen_type'), - (self.frozen_type, 'value'), - ) - # --------------------------------------------------------------------------- + self.children = [ self.error_message, self.warning_message, @@ -379,17 +368,20 @@ def render(self): self.retrieve_matrices, self.compute_fermi_surface, self.params_fermi_surface_vbox, - self.params_dhva_freqs_vbox, self.algorithm_description, self.projection_type, self.warning_message_pdwf, self.frozen_states_widget, self.scan_pdwf_parameter, ] + self.rendered = True - def _on_electronic_type_change(self, change): - if change['new'] == 'insulator': + def _on_electronic_type_change(self, _): + if not self.rendered: + return + + if self._model.electronic_type == 'insulator': self.error_message.value = """
⚠️ Wannierization of insulators: the current automated workflow works only when treating the system as a metal (i.e., include some conduction bands). Please set Electronic type to Metal to proceed, otherwise the submission will be blocked. @@ -402,30 +394,33 @@ def _on_electronic_type_change(self, change): self.error_message.value = '' # Function to toggle the visibility of the energy window input - def _update_energy_window_visibility(self, change): - if change['new'] in ['fixed_plus_projectability', 'energy_fixed']: + def _on_frozen_type_change(self, _): + if not self.rendered: + return + + if self._model.frozen_type in ('fixed_plus_projectability', 'energy_fixed'): self.energy_window_widget.layout.display = 'flex' else: self.energy_window_widget.layout.display = 'none' def _on_compute_fermi_surface_change(self, change): - # Ensure the widget is initialized before accessing it - if self.compute_fermi_surface is None: + if not self.rendered: return - if self.compute_fermi_surface.value: + if self._model.compute_fermi_surface: self.params_fermi_surface_vbox.children = [ self.fermi_surface_kpoint_distance, self.compute_dhva_frequencies, + self.params_dhva_freqs_vbox, ] else: self.params_fermi_surface_vbox.children = [] - def _on_compute_dhva_freqs_change(self, change): - # Ensure the widget is initialized before accessing it - if self.compute_fermi_surface is None: + def _on_compute_dhva_freqs_change(self, _): + if not self.rendered: return - if self.compute_fermi_surface.value and self.compute_dhva_frequencies.value: + + if self._model.compute_fermi_surface and self._model.compute_dhva_frequencies: self.params_dhva_freqs_vbox.children = [ self.dhva_first_row, self.dhva_second_row, From 1696fe1def3f2c4b27879af3f054eb0c4d97526b Mon Sep 17 00:00:00 2001 From: Edan Bainglass Date: Fri, 8 May 2026 09:42:32 +0000 Subject: [PATCH 3/4] Move invalid tooltip to warning note --- src/aiidalab_qe_wannier90/setting.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/aiidalab_qe_wannier90/setting.py b/src/aiidalab_qe_wannier90/setting.py index 9120c80..c32a6d6 100644 --- a/src/aiidalab_qe_wannier90/setting.py +++ b/src/aiidalab_qe_wannier90/setting.py @@ -102,9 +102,6 @@ def render(self): value=self._model.scan_pdwf_parameter, description='Optimize PDWF thresholds', indent=False, - tooltip='If enabled, an exhaustive scan of the PDWF thresholds is ' - 'performed (up to 30 Wannierizations) to find those that bring the ' - 'bands distance (for bands up to 2 eV above the Fermi level) below 10 meV.', ) ipw.link( (self._model, 'scan_pdwf_parameter'), @@ -357,6 +354,15 @@ def render(self): layout=ipw.Layout(width='100%', align_items='flex-start', overflow='visible'), ) + optimize_pdwf_info = ipw.HTML( + """
+ Note: If Optimize PDWF thresholds is enabled, an + exhaustive scan of the PDWF thresholds is performed (up to 30 + Wannierizations) to find those that bring the bands distance (for + bands up to 2 eV above the Fermi level) below 10 meV. +
""" + ) + self.children = [ self.error_message, self.warning_message, @@ -373,6 +379,7 @@ def render(self): self.warning_message_pdwf, self.frozen_states_widget, self.scan_pdwf_parameter, + optimize_pdwf_info, ] self.rendered = True From a9fffbae2d987aa41f4031f630e22937de35e8b1 Mon Sep 17 00:00:00 2001 From: Edan Bainglass Date: Wed, 13 May 2026 05:04:05 +0000 Subject: [PATCH 4/4] Trigger post-render updates --- src/aiidalab_qe_wannier90/setting.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/aiidalab_qe_wannier90/setting.py b/src/aiidalab_qe_wannier90/setting.py index c32a6d6..614e21c 100644 --- a/src/aiidalab_qe_wannier90/setting.py +++ b/src/aiidalab_qe_wannier90/setting.py @@ -384,7 +384,15 @@ def render(self): self.rendered = True + self._toggle_insulator_warning() + self._toggle_energy_window_input() + self._toggle_fermi_surface_parameters() + self._toggle_dhva_freqs_parameters() + def _on_electronic_type_change(self, _): + self._toggle_insulator_warning() + + def _toggle_insulator_warning(self): if not self.rendered: return @@ -400,8 +408,10 @@ def _on_electronic_type_change(self, _): else: self.error_message.value = '' - # Function to toggle the visibility of the energy window input def _on_frozen_type_change(self, _): + self._toggle_energy_window_input() + + def _toggle_energy_window_input(self): if not self.rendered: return @@ -411,6 +421,9 @@ def _on_frozen_type_change(self, _): self.energy_window_widget.layout.display = 'none' def _on_compute_fermi_surface_change(self, change): + self._toggle_fermi_surface_parameters() + + def _toggle_fermi_surface_parameters(self): if not self.rendered: return @@ -424,6 +437,9 @@ def _on_compute_fermi_surface_change(self, change): self.params_fermi_surface_vbox.children = [] def _on_compute_dhva_freqs_change(self, _): + self._toggle_dhva_freqs_parameters() + + def _toggle_dhva_freqs_parameters(self): if not self.rendered: return