Skip to content

Commit

Permalink
phonon tab results
Browse files Browse the repository at this point in the history
  • Loading branch information
AndresOrtegaGuerrero committed Dec 2, 2024
1 parent 194c3b3 commit a2b8d08
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 253 deletions.
252 changes: 1 addition & 251 deletions src/aiidalab_qe_vibroscopy/app/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,14 @@


from aiidalab_qe.common.panel import ResultPanel
from aiidalab_qe.common.bandpdoswidget import BandPdosPlotly
from IPython.display import display
import numpy as np

from ..utils.phonons.result import export_phononworkchain_data

from ..utils.euphonic import (
export_euphonic_data,
EuphonicSuperWidget,
DownloadYamlHdf5Widget,
)
import plotly.graph_objects as go
import ipywidgets as ipw


class PhononBandPdosPlotly(BandPdosPlotly):
def __init__(self, bands_data=None, pdos_data=None):
super().__init__(bands_data, pdos_data)
self._bands_yaxis = go.layout.YAxis(
title=dict(text="Phonon Bands (THz)", standoff=1),
side="left",
showgrid=True,
showline=True,
zeroline=True,
range=self.SETTINGS["vertical_range_bands"],
fixedrange=False,
automargin=True,
ticks="inside",
linewidth=2,
linecolor=self.SETTINGS["axis_linecolor"],
tickwidth=2,
zerolinewidth=2,
)

paths = self.bands_data.get("paths")
slider_bands = go.layout.xaxis.Rangeslider(
thickness=0.08,
range=[0, paths[-1]["x"][-1]],
)
self._bands_xaxis = go.layout.XAxis(
title="q-points",
range=[0, paths[-1]["x"][-1]],
showgrid=True,
showline=True,
tickmode="array",
rangeslider=slider_bands,
fixedrange=False,
tickvals=self.bands_data["pathlabels"][1], # ,self.band_labels[1],
ticktext=self.bands_data["pathlabels"][0], # self.band_labels[0],
showticklabels=True,
linecolor=self.SETTINGS["axis_linecolor"],
mirror=True,
linewidth=2,
type="linear",
)
import ipywidgets as ipw


class Result(ResultPanel):
Expand All @@ -79,87 +32,8 @@ def _update_view(self):
children_result_widget = ()
tab_titles = [] # this is needed to name the sub panels

phonon_data = export_phononworkchain_data(self.node)
ins_data = export_euphonic_data(self.node)

if phonon_data:
phonon_children = ()
if phonon_data["bands"] or phonon_data["pdos"]:
_bands_plot_view_class = PhononBandPdosPlotly(
bands_data=phonon_data["bands"][0],
pdos_data=phonon_data["pdos"][0],
).bandspdosfigure
_bands_plot_view_class.update_layout(
yaxis=dict(autorange=True), # Automatically scale the y-axis
)

# the data (bands and pdos) are the first element of the lists phonon_data["bands"] and phonon_data["pdos"]!
downloadBandsPdos_widget = DownloadBandsPdosWidget(
data=phonon_data,
)
downloadYamlHdf5_widget = DownloadYamlHdf5Widget(
phonopy_node=self.node.outputs.vibronic.phonon_pdos.creator
)

phonon_children += (
_bands_plot_view_class,
ipw.HBox(
children=[
downloadBandsPdos_widget,
downloadYamlHdf5_widget,
]
),
)

if phonon_data["thermo"]:
import plotly.graph_objects as go

T = phonon_data["thermo"][0][0]
F = phonon_data["thermo"][0][1]
F_units = phonon_data["thermo"][0][2]
E = phonon_data["thermo"][0][3]
E_units = phonon_data["thermo"][0][4]
Cv = phonon_data["thermo"][0][5]
Cv_units = phonon_data["thermo"][0][6]

g = go.FigureWidget(
layout=go.Layout(
title=dict(text="Thermal properties"),
barmode="overlay",
)
)
g.update_layout(
xaxis=dict(
title="Temperature (K)",
linecolor="black",
linewidth=2,
showline=True,
),
yaxis=dict(linecolor="black", linewidth=2, showline=True),
plot_bgcolor="white",
)
g.add_scatter(x=T, y=F, name=f"Helmoltz Free Energy ({F_units})")
g.add_scatter(x=T, y=E, name=f"Entropy ({E_units})")
g.add_scatter(x=T, y=Cv, name=f"Specific Heat-V=const ({Cv_units})")

downloadThermo_widget = DownloadThermoWidget(T, F, E, Cv)

phonon_children += (
g,
downloadThermo_widget,
)

tab_titles.append("Phonon properties")

children_result_widget += (
ipw.VBox(
children=phonon_children,
layout=ipw.Layout(
width="100%",
),
),
) # the comma is required! otherwise the tuple is not detected.

# euphonic
if ins_data:
intensity_maps = EuphonicSuperWidget(
Expand All @@ -174,127 +48,3 @@ def _update_view(self):
self.result_tabs.set_title(title_index, tab_titles[title_index])

self.children = [self.result_tabs]


class DownloadBandsPdosWidget(ipw.HBox):
def __init__(self, data, **kwargs):
self.download_button = ipw.Button(
description="Download phonon bands and pdos data",
icon="pencil",
button_style="primary",
disabled=False,
layout=ipw.Layout(width="auto"),
)
self.download_button.on_click(self.download_data)
self.bands_data = data["bands"]
self.pdos_data = data["pdos"]

super().__init__(
children=[
self.download_button,
],
)

def download_data(self, _=None):
"""Function to download the phonon data."""
import json
from monty.json import jsanitize
import base64

file_name_bands = "phonon_bands_data.json"
file_name_pdos = "phonon_dos_data.json"
if self.bands_data[0]:
bands_data_export = {}
for key, value in self.bands_data[0].items():
if isinstance(value, np.ndarray):
bands_data_export[key] = value.tolist()
else:
bands_data_export[key] = value

json_str = json.dumps(jsanitize(bands_data_export))
b64_str = base64.b64encode(json_str.encode()).decode()
self._download(payload=b64_str, filename=file_name_bands)
if self.pdos_data:
json_str = json.dumps(jsanitize(self.pdos_data[0]))
b64_str = base64.b64encode(json_str.encode()).decode()
self._download(payload=b64_str, filename=file_name_pdos)

@staticmethod
def _download(payload, filename):
from IPython.display import Javascript

javas = Javascript(
"""
var link = document.createElement('a');
link.href = 'data:text/json;charset=utf-8;base64,{payload}'
link.download = "{filename}"
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
""".format(payload=payload, filename=filename)
)
display(javas)


class DownloadThermoWidget(ipw.HBox):
def __init__(self, T, F, E, Cv, **kwargs):
self.download_button = ipw.Button(
description="Download thermal properties data",
icon="pencil",
button_style="primary",
disabled=False,
layout=ipw.Layout(width="auto"),
)
self.download_button.on_click(self.download_data)

self.temperature = T
self.free_E = F
self.entropy = E
self.Cv = Cv

super().__init__(
children=[
self.download_button,
],
)

def download_data(self, _=None):
"""Function to download the phonon data."""
import json
import base64

file_name = "phonon_thermo_data.json"
data_export = {}
for key, value in zip(
[
"Temperature (K)",
"Helmoltz Free Energy (kJ/mol)",
"Entropy (J/K/mol)",
"Specific Heat-V=const (J/K/mol)",
],
[self.temperature, self.free_E, self.entropy, self.Cv],
):
if isinstance(value, np.ndarray):
data_export[key] = value.tolist()
else:
data_export[key] = value

json_str = json.dumps(data_export)
b64_str = base64.b64encode(json_str.encode()).decode()
self._download(payload=b64_str, filename=file_name)

@staticmethod
def _download(payload, filename):
from IPython.display import Javascript

javas = Javascript(
"""
var link = document.createElement('a');
link.href = 'data:text/json;charset=utf-8;base64,{payload}'
link.download = "{filename}"
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
""".format(payload=payload, filename=filename)
)
display(javas)
14 changes: 12 additions & 2 deletions src/aiidalab_qe_vibroscopy/app/result/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
from aiidalab_qe_vibroscopy.app.widgets.ir_ramanwidget import IRRamanWidget
from aiidalab_qe_vibroscopy.app.widgets.ir_ramanmodel import IRRamanModel

from aiidalab_qe_vibroscopy.app.widgets.phononwidget import PhononWidget
from aiidalab_qe_vibroscopy.app.widgets.phononmodel import PhononModel


class VibroResultsPanel(ResultsPanel[VibroResultsModel]):
title = "Vibronic"
Expand All @@ -32,8 +35,15 @@ def render(self):
tab_data = []
vibro_node = self._model.get_vibro_node()

if self._model.needs_phonons_tab():
tab_data.append(("Phonons", ipw.HTML("phonon_data")))
needs_phonons_tab = self._model.needs_phonons_tab()
if needs_phonons_tab:
vibroscopy_node = self._model._fetch_child_process_node()
phonon_model = PhononModel()
phonon_widget = PhononWidget(
model=phonon_model,
node=vibroscopy_node,
)
tab_data.append(("Phonons", phonon_widget))

needs_raman_tab = self._model.needs_raman_tab()
if needs_raman_tab:
Expand Down
Loading

0 comments on commit a2b8d08

Please sign in to comment.