Skip to content

Commit

Permalink
more refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mikibonacci committed Dec 9, 2024
1 parent 8d3a3da commit 4ac8a33
Show file tree
Hide file tree
Showing 8 changed files with 387 additions and 211 deletions.
15 changes: 11 additions & 4 deletions src/aiidalab_qe_vibroscopy/app/widgets/euphonicmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@
import traitlets as tl
import copy

from aiidalab_qe_vibroscopy.utils.euphonic.data_manipulation.intensity_maps import (
from aiidalab_qe_vibroscopy.utils.euphonic.data.structure_factors import (
AttrDict,
produce_bands_weigthed_data,
produce_powder_data,
generated_curated_data,
par_dict,
par_dict_powder,
export_euphonic_data,
generate_force_constant_instance,
)

from aiidalab_qe_vibroscopy.utils.euphonic.data.parameters import (
parameters_single_crystal,
parameters_powder,
)


from aiidalab_qe_vibroscopy.utils.euphonic.tab_widgets.euphonic_q_planes_widgets import (
produce_Q_section_modes,
produce_Q_section_spectrum,
Expand All @@ -21,7 +25,7 @@
from aiidalab_qe.common.mvc import Model


class EuphonicBaseResultsModel(Model):
class EuphonicResultsModel(Model):
"""Model for the neutron scattering results panel."""

# Here we mode all the model and data-controller, i.e. all the data and their
Expand Down Expand Up @@ -73,6 +77,9 @@ def reset(
def fetch_data(self):
"""Fetch the data from the database or from the uploaded files."""
# 1. from aiida, so we have the node
if hasattr(self, "fc"):
# we already have the data (this happens if I clone the model with already the data inside)
return
if self.node:
ins_data = export_euphonic_data(self.node)
self.fc = ins_data["fc"]
Expand Down
209 changes: 55 additions & 154 deletions src/aiidalab_qe_vibroscopy/app/widgets/euphonicwidget.py
Original file line number Diff line number Diff line change
@@ -1,125 +1,28 @@
import pathlib
import tempfile


import ipywidgets as ipw
from IPython.display import display

import ipywidgets as ipw
from aiidalab_qe.common.widgets import LoadingWidget

# from ..euphonic.bands_pdos import *
from aiidalab_qe_vibroscopy.utils.euphonic.data_manipulation.intensity_maps import (
from aiidalab_qe_vibroscopy.utils.euphonic.data.structure_factors import (
generate_force_constant_instance,
export_euphonic_data, # noqa: F401
)
from aiidalab_qe_vibroscopy.utils.euphonic.tab_widgets.euphonic_single_crystal_widgets import (
SingleCrystalFullWidget,
)
from aiidalab_qe_vibroscopy.utils.euphonic.tab_widgets.euphonic_powder_widgets import (
PowderFullWidget,
)
from aiidalab_qe_vibroscopy.utils.euphonic.tab_widgets.euphonic_q_planes_widgets import (
QSectionFullWidget,
)


from aiidalab_qe.common.widgets import LoadingWidget
###### START for detached app:


# Upload buttons
class UploadPhonopyYamlWidget(ipw.FileUpload):
def __init__(self, **kwargs):
super().__init__(
description="upload phonopy YAML file",
multiple=False,
layout={"width": "initial"},
)


class UploadForceConstantsHdf5Widget(ipw.FileUpload):
def __init__(self, **kwargs):
super().__init__(
description="upload force constants HDF5 file",
multiple=False,
layout={"width": "initial"},
)


class UploadPhonopyWidget(ipw.HBox):
def __init__(self, **kwargs):
self.upload_phonopy_yaml = UploadPhonopyYamlWidget(**kwargs)
self.upload_phonopy_hdf5 = UploadForceConstantsHdf5Widget(**kwargs)

self.reset_uploads = ipw.Button(
description="Discard uploaded files",
icon="pencil",
button_style="warning",
disabled=False,
layout=ipw.Layout(width="auto"),
)

super().__init__(
children=[
self.upload_phonopy_yaml,
self.upload_phonopy_hdf5,
self.reset_uploads,
],
**kwargs,
)

def _read_phonopy_files(self, fname, phonopy_yaml_content, fc_hdf5_content=None):
suffix = "".join(pathlib.Path(fname).suffixes)

with tempfile.NamedTemporaryFile(suffix=suffix) as temp_yaml:
temp_yaml.write(phonopy_yaml_content)
temp_yaml.flush()

if fc_hdf5_content:
with tempfile.NamedTemporaryFile(suffix=".hdf5") as temp_file:
temp_file.write(fc_hdf5_content)
temp_file.flush()
temp_hdf5_name = temp_file.name

try:
fc = generate_force_constant_instance(
path=pathlib.Path(fname),
summary_name=temp_yaml.name,
fc_name=temp_hdf5_name,
)
except ValueError:
return None

return fc
else:
temp_hdf5_name = None

try:
fc = generate_force_constant_instance(
path=pathlib.Path(fname),
summary_name=temp_yaml.name,
# fc_name=temp_hdf5_name,
)
except ValueError:
return None

return fc


#### END for detached app
from aiidalab_qe_vibroscopy.app.widgets.structurefactorwidget import EuphonicStructureFactorWidget


##### START OVERALL WIDGET TO DISPLAY EVERYTHING:


class EuphonicSuperWidget(ipw.VBox):
class EuphonicWidget(ipw.VBox):
"""
Widget that will include everything,
from the upload widget to the tabs with single crystal and powder predictions.
In between, we trigger the initialization of plots via a button.
"""

def __init__(
self, mode="aiidalab-qe app plugin", model=None, node=None, fc=None, q_path=None
self, model: EuphonicResultsModel, node=None, detached_app = False, **kwargs,
):
"""
Initialize the Euphonic utility class.
Expand Down Expand Up @@ -147,23 +50,20 @@ def __init__(
fc : optional
Force constants if provided.
"""

self.mode = mode

super().__init__()

self._model = model # this is the single crystal model.
self._model.node = node
if node: self._model.vibro = node
self._model.detached_app = detached_app
self._model.fc_hdf5_content = None

self.rendered = False

super().__init__()

def render(self):
if self.rendered:
return

self.upload_widget = UploadPhonopyWidget()
self.upload_widget.reset_uploads.on_click(self._on_reset_uploads_button_clicked)


self.tab_widget = ipw.Tab()
self.tab_widget.layout.display = "none"
self.tab_widget.set_title(0, "Single crystal")
Expand All @@ -178,31 +78,64 @@ def render(self):
disabled=True,
layout=ipw.Layout(width="auto"),
)
self.plot_button.on_click(self._on_first_plot_button_clicked)
self.plot_button.on_click(self._render_for_real)

self.loading_widget = LoadingWidget("Loading INS data")
self.loading_widget.layout.display = "none"

if self.mode == "aiidalab-qe app plugin":
self.upload_widget.layout.display = "none"
if not self._model.detached_app:
self.plot_button.disabled = False
else:
from aiidalab_qe_vibroscopy.utils.euphonic.detached_app.uploadwidgets import UploadPhonopyWidget
self.upload_widget = UploadPhonopyWidget()
self.upload_widget.reset_uploads.on_click(self._on_reset_uploads_button_clicked)
self.upload_widget.children[0].observe(self._on_upload_yaml, "_counter")
self.upload_widget.children[1].observe(self._on_upload_hdf5, "_counter")

self.children += (self.upload_widget,)

self.download_widget = DownloadYamlHdf5Widget(model=self._model)
self.download_widget.layout.display = "none"

self.children = [
self.upload_widget,
self.children += (
self.plot_button,
self.loading_widget,
self.tab_widget,
self.download_widget,
]

self.loading_widget,
)

self.rendered = True

def _render_for_real(self, change=None):
# It creates the widgets
self.plot_button.layout.display = "none"
self.loading_widget.layout.display = "block"

self._model.fetch_data() # should be in the model, but I can do it here once for all and then clone the model.
powder_model = self._model._clone()
qsection_model = self._model._clone()

# I first initialise this widget, to then have the 0K ref for the other two.
# the model is passed to the widget. For the other two, I need to generate the model.
singlecrystalwidget = SingleCrystalFullWidget(model=self._model)

# I need to generate the models for the other two widgets.
self._model._inject_single_crystal_settings()
powder_model._inject_powder_settings()
qsection_model._inject_qsection_settings()

self.tab_widget.children = (
singlecrystalwidget,
PowderFullWidget(model=powder_model),
QSectionFullWidget(model=qsection_model),
)

for widget in self.tab_widget.children:
widget.render() # this is the render method of the widget.

self.loading_widget.layout.display = "none"
self.tab_widget.layout.display = "block"
self.download_widget.layout.display = "block"

def _on_reset_uploads_button_clicked(self, change):
self.upload_widget.upload_phonopy_yaml.value.clear()
self.upload_widget.upload_phonopy_yaml._counter = 0
Expand Down Expand Up @@ -235,39 +168,7 @@ def _on_upload_hdf5(self, change):
self._model.fc_hdf5_content = self.upload_widget.children[1].value[
fname
]["content"]

def _on_first_plot_button_clicked(self, change=None): # basically the render.
# It creates the widgets
self.plot_button.layout.display = "none"
self.loading_widget.layout.display = "block"

self._model.fetch_data() # should be in the model.
powder_model = self._model._clone()
qsection_model = self._model._clone()

# I first initialise this widget, to then have the 0K ref for the other two.
# the model is passed to the widget. For the other two, I need to generate the model.
singlecrystalwidget = SingleCrystalFullWidget(model=self._model)

# I need to generate the models for the other two widgets.
self._model._inject_single_crystal_settings()
powder_model._inject_powder_settings()
qsection_model._inject_qsection_settings()

self.tab_widget.children = (
singlecrystalwidget,
PowderFullWidget(model=powder_model),
QSectionFullWidget(model=qsection_model),
)

for widget in self.tab_widget.children:
widget.render() # this is the render method of the widget.

self.loading_widget.layout.display = "none"
self.tab_widget.layout.display = "block"
self.download_widget.layout.display = "block"



class DownloadYamlHdf5Widget(ipw.HBox):
def __init__(self, model):
self._model = model
Expand Down
Loading

0 comments on commit 4ac8a33

Please sign in to comment.