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)
diff --git a/src/aiidalab_qe_wannier90/setting.py b/src/aiidalab_qe_wannier90/setting.py
index 68dfdb0..614e21c 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,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'),
@@ -125,7 +118,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 +149,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 +210,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_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_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_third_row = ipw.IntText(
value=self._model.dhva_num_rotation,
description='Number of rotation steps',
@@ -274,7 +268,6 @@ def render(self):
"""
)
-
# Dropdown for Projection Type
self.projection_type = ipw.Dropdown(
options=[
@@ -291,7 +284,6 @@ def render(self):
layout=ipw.Layout(width='700px'),
)
-
ipw.link(
(self._model, 'projection_type'),
(self.projection_type, 'value'),
@@ -325,6 +317,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 +334,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 +353,16 @@ 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'),
+
+ 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,
@@ -379,17 +374,29 @@ 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,
+ optimize_pdwf_info,
]
+
self.rendered = True
- def _on_electronic_type_change(self, change):
- if change['new'] == 'insulator':
+ 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
+
+ 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.
@@ -401,31 +408,42 @@ def _on_electronic_type_change(self, change):
else:
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, _):
+ self._toggle_energy_window_input()
+
+ def _toggle_energy_window_input(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:
+ self._toggle_fermi_surface_parameters()
+
+ def _toggle_fermi_surface_parameters(self):
+ 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, _):
+ self._toggle_dhva_freqs_parameters()
+
+ def _toggle_dhva_freqs_parameters(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,