From 8ea879c2a5ed1589fa33fbca300223c2fbe88508 Mon Sep 17 00:00:00 2001 From: AndresOrtegaGuerrero Date: Sat, 30 Nov 2024 10:43:46 +0000 Subject: [PATCH] template of result tabs --- src/aiidalab_qe_vibroscopy/app/__init__.py | 6 +++ .../app/result/model.py | 19 ++++++++++ .../app/result/result.py | 31 +++++++++++++++ .../app/widgets/dielectricmodel.py | 9 +++++ .../app/widgets/dielectricwidget.py | 38 +++++++++++++++++++ .../utils/dielectric/result.py | 19 ++++------ .../utils/euphonic/intensity_maps.py | 10 ++--- .../utils/phonons/result.py | 33 ++++++++-------- .../utils/raman/result.py | 15 +++----- 9 files changed, 134 insertions(+), 46 deletions(-) create mode 100644 src/aiidalab_qe_vibroscopy/app/widgets/dielectricmodel.py create mode 100644 src/aiidalab_qe_vibroscopy/app/widgets/dielectricwidget.py diff --git a/src/aiidalab_qe_vibroscopy/app/__init__.py b/src/aiidalab_qe_vibroscopy/app/__init__.py index e77ed16..361de09 100644 --- a/src/aiidalab_qe_vibroscopy/app/__init__.py +++ b/src/aiidalab_qe_vibroscopy/app/__init__.py @@ -6,6 +6,8 @@ VibroResourceSettingsModel, VibroResourcesSettingsPanel, ) +from aiidalab_qe_vibroscopy.app.result.result import VibroResultsPanel +from aiidalab_qe_vibroscopy.app.result.model import VibroResultsModel from aiidalab_qe_vibroscopy.app.workchain import workchain_and_builder @@ -24,5 +26,9 @@ class VibroPluginOutline(PluginOutline): "panel": VibroResourcesSettingsPanel, "model": VibroResourceSettingsModel, }, + "result": { + "panel": VibroResultsPanel, + "model": VibroResultsModel, + }, "workchain": workchain_and_builder, } diff --git a/src/aiidalab_qe_vibroscopy/app/result/model.py b/src/aiidalab_qe_vibroscopy/app/result/model.py index 23c2a29..3196fc0 100644 --- a/src/aiidalab_qe_vibroscopy/app/result/model.py +++ b/src/aiidalab_qe_vibroscopy/app/result/model.py @@ -1,6 +1,11 @@ from aiidalab_qe.common.panel import ResultsModel import traitlets as tl +from aiidalab_qe_vibroscopy.utils.dielectric.result import export_dielectric_data +from aiidalab_qe_vibroscopy.utils.raman.result import export_iramanworkchain_data +from aiidalab_qe_vibroscopy.utils.phonons.result import export_phononworkchain_data +from aiidalab_qe_vibroscopy.utils.euphonic import export_euphonic_data + class VibroResultsModel(ResultsModel): identifier = "vibronic" @@ -11,3 +16,17 @@ class VibroResultsModel(ResultsModel): def get_vibro_node(self): return self._get_child_outputs() + + def needs_dielectric_tab(self): + return export_dielectric_data(self.get_vibro_node()) + + def needs_raman_tab(self): + return export_iramanworkchain_data(self.get_vibro_node()) + + # Here we use _fetch_child_process_node() since the function needs the input_structure in inputs + def needs_phonons_tab(self): + return export_phononworkchain_data(self._fetch_child_process_node()) + + # Here we use _fetch_child_process_node() since the function needs the input_structure in inputs + def needs_euphonic_tab(self): + return export_euphonic_data(self._fetch_child_process_node()) diff --git a/src/aiidalab_qe_vibroscopy/app/result/result.py b/src/aiidalab_qe_vibroscopy/app/result/result.py index d709802..849bb56 100644 --- a/src/aiidalab_qe_vibroscopy/app/result/result.py +++ b/src/aiidalab_qe_vibroscopy/app/result/result.py @@ -3,6 +3,8 @@ from aiidalab_qe_vibroscopy.app.result.model import VibroResultsModel from aiidalab_qe.common.panel import ResultsPanel +import ipywidgets as ipw + class VibroResultsPanel(ResultsPanel[VibroResultsModel]): title = "Vibronic" @@ -12,3 +14,32 @@ class VibroResultsPanel(ResultsPanel[VibroResultsModel]): def render(self): if self.rendered: return + + self.tabs = ipw.Tab( + layout=ipw.Layout(min_height="250px"), + selected_index=None, + ) + + tab_data = [] + # vibro_node = self._model.get_vibro_node() + + if self._model.needs_phonons_tab(): + tab_data.append(("Phonons", ipw.HTML("phonon_data"))) + + if self._model.needs_raman_tab(): + tab_data.append(("Raman", ipw.HTML("raman_data"))) + + if self._model.needs_dielectric_tab(): + tab_data.append(("Dielectric", ipw.HTML("dielectric_data"))) + + if self._model.needs_euphonic_tab(): + tab_data.append(("Euphonic", ipw.HTML("euphonic_data"))) + + # Assign children and titles dynamically + self.tabs.children = [content for _, content in tab_data] + + for index, (title, _) in enumerate(tab_data): + self.tabs.set_title(index, title) + + self.children = [self.tabs] + self.rendered = True diff --git a/src/aiidalab_qe_vibroscopy/app/widgets/dielectricmodel.py b/src/aiidalab_qe_vibroscopy/app/widgets/dielectricmodel.py new file mode 100644 index 0000000..6b76f76 --- /dev/null +++ b/src/aiidalab_qe_vibroscopy/app/widgets/dielectricmodel.py @@ -0,0 +1,9 @@ +from aiidalab_qe.common.mvc import Model +from aiida.common.extendeddicts import AttributeDict +import traitlets as tl + + +class DielectricModel(Model): + vibro = tl.Instance(AttributeDict, allow_none=True) + + dielectric_data = {} diff --git a/src/aiidalab_qe_vibroscopy/app/widgets/dielectricwidget.py b/src/aiidalab_qe_vibroscopy/app/widgets/dielectricwidget.py new file mode 100644 index 0000000..4a57b75 --- /dev/null +++ b/src/aiidalab_qe_vibroscopy/app/widgets/dielectricwidget.py @@ -0,0 +1,38 @@ +import ipywidgets as ipw +from aiidalab_qe_vibroscopy.app.widgets.dielectricmodel import DielectricModel +from aiidalab_qe.common.widgets import LoadingWidget + + +class DielectricWidget(ipw.VBox): + """ + Widget for displaying dielectric properties results + """ + + def __init__(self, model: DielectricModel, dielectric_node: None, **kwargs): + super().__init__( + children=[LoadingWidget("Loading widgets")], + **kwargs, + ) + self._model = model + + def render(self): + if self.rendered: + return + + self.dielectric_results_help = ipw.HTML( + """
+ The DielectricWorkchain computes different properties:
+ -High Freq. Dielectric Tensor
+ -Born Charges
+ -Raman Tensors
+ -The non-linear optical susceptibility tensor
+ All information can be downloaded as a JSON file.
+ +
""" + ) + + self.children = [ + self.dielectric_results_help, + ] + + self.rendered = True diff --git a/src/aiidalab_qe_vibroscopy/utils/dielectric/result.py b/src/aiidalab_qe_vibroscopy/utils/dielectric/result.py index ecccf70..2bec7dd 100644 --- a/src/aiidalab_qe_vibroscopy/utils/dielectric/result.py +++ b/src/aiidalab_qe_vibroscopy/utils/dielectric/result.py @@ -59,23 +59,18 @@ def get_priority_tensor(filtered_node): def export_dielectric_data(node): - if "vibronic" not in node.outputs: - return None - - if not any( - key in node.outputs.vibronic for key in ["iraman", "dielectric", "harmonic"] - ): + if not any(key in node for key in ["iraman", "dielectric", "harmonic"]): return None else: - if "iraman" in node.outputs.vibronic: - vibrational_data = node.outputs.vibronic.iraman.vibrational_data + if "iraman" in node: + vibrational_data = node.iraman.vibrational_data - elif "harmonic" in node.outputs.vibronic: - vibrational_data = node.outputs.vibronic.harmonic.vibrational_data + elif "harmonic" in node: + vibrational_data = node.harmonic.vibrational_data - elif "dielectric" in node.outputs.vibronic: - tensor_data = node.outputs.vibronic.dielectric + elif "dielectric" in node: + tensor_data = node.dielectric output_data = get_priority_tensor(tensor_data) dielectric_tensor = output_data.get_array("dielectric").round( 6 diff --git a/src/aiidalab_qe_vibroscopy/utils/euphonic/intensity_maps.py b/src/aiidalab_qe_vibroscopy/utils/euphonic/intensity_maps.py index 6a7490b..1e59580 100644 --- a/src/aiidalab_qe_vibroscopy/utils/euphonic/intensity_maps.py +++ b/src/aiidalab_qe_vibroscopy/utils/euphonic/intensity_maps.py @@ -759,17 +759,13 @@ def generate_force_constant_instance( def export_euphonic_data(node, fermi_energy=None): - if "vibronic" not in node.outputs: - # Not a phonon calculation + if "phonon_bands" not in node.outputs: return None - else: - if "phonon_bands" not in node.outputs.vibronic: - return None - output_set = node.outputs.vibronic.phonon_bands + output_set = node.outputs.phonon_bands if any(not element for element in node.inputs.structure.pbc): - vibro_bands = node.inputs.vibronic.phonopy_bands_dict.get_dict() + vibro_bands = node.inputs.phonopy_bands_dict.get_dict() # Group the band and band_labels band = vibro_bands["band"] band_labels = vibro_bands["band_labels"] diff --git a/src/aiidalab_qe_vibroscopy/utils/phonons/result.py b/src/aiidalab_qe_vibroscopy/utils/phonons/result.py index 7b1296c..49a2759 100644 --- a/src/aiidalab_qe_vibroscopy/utils/phonons/result.py +++ b/src/aiidalab_qe_vibroscopy/utils/phonons/result.py @@ -1,6 +1,6 @@ """Bands results view widgets""" -from aiidalab_qe.common.bandpdoswidget import cmap, get_bands_labeling +from aiidalab_qe.common.bands_pdos.utils import _cmap, _get_bands_labeling import numpy as np import json @@ -34,25 +34,22 @@ def export_phononworkchain_data(node, fermi_energy=None): } parameters = {} - if "vibronic" not in node.outputs: - return None - - if "phonon_bands" in node.outputs.vibronic: + if "phonon_bands" in node.outputs: """ copied and pasted from aiidalab_qe.common.bandsplotwidget. adapted for phonon outputs """ data = json.loads( - node.outputs.vibronic.phonon_bands._exportcontent("json", comments=False)[0] + node.outputs.phonon_bands._exportcontent("json", comments=False)[0] ) # The fermi energy from band calculation is not robust. data["fermi_energy"] = 0 - data["pathlabels"] = get_bands_labeling(data) + data["pathlabels"] = _get_bands_labeling(data) replace_symbols_with_uppercase(data["pathlabels"]) data["Y_label"] = "Dispersion (THz)" - bands = node.outputs.vibronic.phonon_bands._get_bandplot_data( + bands = node.outputs.phonon_bands._get_bandplot_data( cartesian=True, prettify_format=None, join_symbol=None, get_segments=True ) parameters["energy_range"] = { @@ -64,8 +61,8 @@ def export_phononworkchain_data(node, fermi_energy=None): data["y"] = bands["y"] full_data["bands"] = [data, parameters] - if "phonon_pdos" in node.outputs.vibronic: - phonopy_calc = node.outputs.vibronic.phonon_pdos.creator + if "phonon_pdos" in node.outputs: + phonopy_calc = node.outputs.phonon_pdos.creator kwargs = {} if "settings" in phonopy_calc.inputs: @@ -75,7 +72,7 @@ def export_phononworkchain_data(node, fermi_energy=None): kwargs.update({key: the_settings[key]}) symbols = node.inputs.structure.get_ase().get_chemical_symbols() - pdos = node.outputs.vibronic.phonon_pdos + pdos = node.outputs.phonon_pdos index_dict, dos_dict = ( {}, @@ -119,8 +116,8 @@ def export_phononworkchain_data(node, fermi_energy=None): "label": atom, "x": pdos.get_x()[1].tolist(), "y": dos_dict[atom].tolist(), - "borderColor": cmap(atom), - "backgroundColor": cmap(atom), + "borderColor": _cmap(atom), + "backgroundColor": _cmap(atom), "backgroundAlpha": "40%", "lineStyle": "solid", } @@ -140,27 +137,27 @@ def export_phononworkchain_data(node, fermi_energy=None): full_data["pdos"] = [json.loads(json.dumps(data_dict)), parameters, "dos"] - if "phonon_thermo" in node.outputs.vibronic: + if "phonon_thermo" in node.outputs: ( what, T, units_k, - ) = node.outputs.vibronic.phonon_thermo.get_x() + ) = node.outputs.phonon_thermo.get_x() ( F_name, F_data, units_F, - ) = node.outputs.vibronic.phonon_thermo.get_y()[0] + ) = node.outputs.phonon_thermo.get_y()[0] ( Entropy_name, Entropy_data, units_entropy, - ) = node.outputs.vibronic.phonon_thermo.get_y()[1] + ) = node.outputs.phonon_thermo.get_y()[1] ( Cv_name, Cv_data, units_Cv, - ) = node.outputs.vibronic.phonon_thermo.get_y()[2] + ) = node.outputs.phonon_thermo.get_y()[2] full_data["thermo"] = ( [T, F_data, units_F, Entropy_data, units_entropy, Cv_data, units_Cv], diff --git a/src/aiidalab_qe_vibroscopy/utils/raman/result.py b/src/aiidalab_qe_vibroscopy/utils/raman/result.py index cb8287d..bf47932 100644 --- a/src/aiidalab_qe_vibroscopy/utils/raman/result.py +++ b/src/aiidalab_qe_vibroscopy/utils/raman/result.py @@ -43,16 +43,13 @@ def export_iramanworkchain_data(node): We have multiple choices: IR, RAMAN. """ - if "vibronic" not in node.outputs: - return None + if "iraman" in node: + output_node = node.iraman + elif "harmonic" in node: + output_node = node.harmonic else: - if "iraman" in node.outputs.vibronic: - output_node = node.outputs.vibronic.iraman - elif "harmonic" in node.outputs.vibronic: - output_node = node.outputs.vibronic.harmonic - else: - # we have raman and ir only if we run IRamanWorkChain or HarmonicWorkChain - return None + # we have raman and ir only if we run IRamanWorkChain or HarmonicWorkChain + return None if "vibrational_data" in output_node: # We enable the possibility to provide both spectra.