Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding raman plot widget #12

Merged
merged 1 commit into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 195 additions & 1 deletion aiidalab_qe_vibroscopy/utils/raman/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
from widget_bandsplot import BandsPlotWidget

from aiidalab_qe.common.panel import ResultPanel

import ipywidgets as ipw
import numpy as np
from IPython.display import clear_output, display
import base64
import json


from aiida_vibroscopy.utils.broadenings import multilorentz
def plot_powder(
Expand Down Expand Up @@ -110,6 +114,196 @@ def _update_view(self):
g,
]

class SpectrumPlotWidget(ipw.VBox):
"""Widget that allows different options for plotting Raman Spectrum."""

description = ipw.HTML(
"""<div style="line-height: 140%; padding-top: 10px; padding-bottom: 10px">
Select the type of Raman spectrum to plot.
</div>"""
)
def __init__(self, node, **kwargs):
self.node = node
#VibriationalData
self.vibro = self.node.outputs.vibronic.iraman.vibrational_data.numerical_accuracy_4
self._plot_type = ipw.ToggleButtons(
options=[
("Powder", "powder"),
("Single Crystal", "single_crystal"),
],
value="powder",
description="Spectrum type:",
disabled=False,
style={"description_width": "initial"},
)
self.temperature = ipw.FloatText(
value=298.0,
description="Temperature (K):",
disabled=False,
style={"description_width": "initial"},
)
self.frequency_laser = ipw.FloatText(
value=532.0,
description="Laser frequency (nm):",
disabled=False,
style={"description_width": "initial"},
)
self.pol_incoming = ipw.Text(
value="0 0 1",
description="Incoming polarization:",
disabled=False,
style={"description_width": "initial"},
)
self.pol_outgoing = ipw.Text(
value="0 0 1",
description="Outgoing polarization:",
disabled=False,
style={"description_width": "initial"},
)
self.plot_button = ipw.Button(
description="Plot",
icon="pencil",
button_style="primary",
disabled=False,
layout=ipw.Layout(width="auto"),
)
self.download_button = ipw.Button(
description="Download Data",
icon="download",
button_style="primary",
disabled=False,
layout=ipw.Layout(width="auto", visibility="hidden"),
)
self.wrong_syntax = ipw.HTML(
value="""<i class="fa fa-times" style="color:red;font-size:2em;" ></i> wrong syntax""",
layout={"visibility": "hidden"},
)
self.spectrum_widget = ipw.Output()
self.frequencies = []
self.intensities = []
self.polarization_out = ipw.Output()

def download_data(_=None):
filename = "spectra.json"
my_dict = {"Frequencies cm-1": self.frequencies.tolist(), "Intensities": self.intensities.tolist()}
json_str = json.dumps(my_dict)
b64_str = base64.b64encode(json_str.encode()).decode()
self._download(payload=b64_str, filename=filename)


self._plot_type.observe(self._on_plot_type_change, names="value")
self.plot_button.on_click(self._on_plot_button_clicked)
self.download_button.on_click(download_data)
super().__init__(
children=[
self.description,
self._plot_type,
self.temperature,
self.frequency_laser,
self.polarization_out,
ipw.HBox([self.plot_button, self.download_button]),
self.wrong_syntax,
self.spectrum_widget,
]
)

@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)

def _on_plot_type_change(self, change):
if change["new"] == "single_crystal":
with self.polarization_out:
clear_output()
display(self.pol_incoming)
display(self.pol_outgoing)
else:
self.pol_incoming.value = "0 0 1"
self.pol_outgoing.value = "0 0 1"
self.wrong_syntax.layout.visibility = "hidden"
with self.polarization_out:
clear_output()

def _on_plot_button_clicked(self, change):
if self._plot_type.value == "powder":
# Powder spectrum
polarized_intensities, depolarized_intensities, frequencies, labels = self.vibro.run_powder_raman_intensities(frequencies=self.frequency_laser.value, temperature=self.temperature.value)
total_intensities = polarized_intensities + depolarized_intensities
self.frequencies , self.intensities = plot_powder(frequencies, total_intensities)
self._display_figure()


else:
# Single crystal spectrum
dir_incoming, correct_syntax_incoming = self._check_inputs_correct(self.pol_incoming)
dir_outgoing, correct_syntax_outgoing = self._check_inputs_correct(self.pol_outgoing)
if not correct_syntax_incoming or not correct_syntax_outgoing:
self.wrong_syntax.layout.visibility = "visible"
return
else:
self.wrong_syntax.layout.visibility = "hidden"
intensities, frequencies, labels = self.vibro.run_single_crystal_raman_intensities(pol_incoming=dir_incoming, pol_outgoing=dir_incoming, frequencies=self.frequency_laser.value, temperature=self.temperature.value)
self.frequencies , self.intensities = plot_powder(frequencies, intensities)
self._display_figure()

def _check_inputs_correct(self,polarization):
#Check if the polarization vectors are correct
input_text = polarization.value
input_values = input_text.split()
dir_values = []
if len(input_values) == 3:
try:
dir_values = [float(i) for i in input_values]
return dir_values, True
except:
return dir_values, False
else:
return dir_values, False

def _spectrum_widget(self):
import plotly.graph_objects as go

fig = go.FigureWidget(
layout=go.Layout(
title=dict(text="Raman spectrum"),
barmode="overlay",
)
)
fig.layout.xaxis.title = "Wavenumber (cm-1)"
fig.layout.yaxis.title = "Intensity (arb. units)"
fig.layout.xaxis.nticks = 0
fig.add_scatter(x=self.frequencies,y=self.intensities,name=f"")
fig.update_layout(
height=500,
width=700,
plot_bgcolor="white",


)
return fig

def _display_figure(self):
with self.spectrum_widget:
clear_output()
display(self._spectrum_widget())
self.download_button.layout.visibility = "visible"






Expand Down
21 changes: 4 additions & 17 deletions aiidalab_qe_vibroscopy/workflows/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from ..utils.raman.result import export_iramanworkchain_data
from ..utils.harmonic.result import export_phononworkchain_data
import ipywidgets as ipw

from ..utils.raman.result import SpectrumPlotWidget
class Result(ResultPanel):

title = "Vibrational Structure"
Expand Down Expand Up @@ -45,27 +45,14 @@ def _update_view(self):
table_html += "</table>"

active_modes = ipw.VBox([ipw.HTML(value="<b> Raman Active Modes </b>"),ipw.HTML(value=table_html)])

spectrum_widget = SpectrumPlotWidget(self.node)

if spectra_data[3] in ["Raman vibrational spectrum","Infrared vibrational spectrum"]:
import plotly.graph_objects as go

frequencies = spectra_data[1]
total_intensities = spectra_data[0]

g = go.FigureWidget(
layout=go.Layout(
title=dict(text=spectra_data[3]),
barmode="overlay",
)
)
g.layout.xaxis.title = "Wavenumber (cm-1)"
g.layout.yaxis.title = "Intensity (arb. units)"
g.layout.xaxis.nticks = 0
g.add_scatter(x=frequencies,y=total_intensities,name=f"")


self.children=[
ipw.HBox([active_modes, g])
ipw.HBox([spectrum_widget, active_modes ])
]

if phonon_data:
Expand Down