diff --git a/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_powder_widgets.py b/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_powder_widgets.py
index f5e86d6..8543482 100644
--- a/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_powder_widgets.py
+++ b/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_powder_widgets.py
@@ -1,33 +1,30 @@
-import pathlib
-import tempfile
-import io
-
import base64
-from IPython.display import HTML, clear_output, display
+from IPython.display import display
-import euphonic
-from phonopy.file_IO import write_force_constants_to_hdf5, write_disp_yaml
import ipywidgets as ipw
import plotly.graph_objects as go
import plotly.io as pio
+import numpy as np
# from ..euphonic.bands_pdos import *
-from ..euphonic.intensity_maps import *
+from ..euphonic.intensity_maps import produce_powder_data, parameters_powder, AttrDict
import json
from monty.json import jsanitize
# sys and os used to prevent euphonic to print in the stdout.
-import sys
-import os
-from aiidalab_qe_vibroscopy.utils.euphonic.euphonic_base_widgets import *
+from aiidalab_qe_vibroscopy.utils.euphonic.euphonic_base_widgets import (
+ StructureFactorBasePlotWidget,
+ StructureFactorSettingsBaseWidget,
+ COLORBAR_DICT,
+ COLORSCALE,
+)
class PowderPlotWidget(StructureFactorBasePlotWidget):
def __init__(self, spectra, intensity_ref_0K=1, **kwargs):
-
final_zspectra = spectra.z_data.magnitude
final_xspectra = spectra.x_data.magnitude
# Data to contour is the sum of two Gaussian functions.
@@ -57,9 +54,8 @@ def __init__(self, spectra, intensity_ref_0K=1, **kwargs):
)
def _update_spectra(self, spectra):
-
final_zspectra = spectra.z_data.magnitude
- final_xspectra = spectra.x_data.magnitude
+ final_xspectra = spectra.x_data.magnitude # noqa: F841
# Data to contour is the sum of two Gaussian functions.
x, y = np.meshgrid(spectra.x_data.magnitude, spectra.y_data.magnitude)
@@ -73,9 +69,11 @@ def _update_spectra(self, spectra):
self.fig.add_trace(
go.Heatmap(
z=final_zspectra.T,
- y=y[:, 0] * self.THz_to_meV
- if self.E_units_button.value == "meV"
- else y[:, 0],
+ y=(
+ y[:, 0] * self.THz_to_meV
+ if self.E_units_button.value == "meV"
+ else y[:, 0]
+ ),
x=x,
colorbar=COLORBAR_DICT,
colorscale=COLORSCALE, # imported from euphonic_base_widgets
@@ -93,7 +91,6 @@ def _update_spectra(self, spectra):
class PowderSettingsWidget(StructureFactorSettingsBaseWidget):
def __init__(self, **kwargs):
-
self.float_qmin = ipw.FloatText(
value=0,
description="|q|
min (1/A)",
@@ -173,7 +170,6 @@ class PowderFullWidget(ipw.VBox):
"""
def __init__(self, fc, intensity_ref_0K=1, **kwargs):
-
self.fc = fc
self.spectra, self.parameters = produce_powder_data(
@@ -278,8 +274,6 @@ def _download(payload, filename):
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
- """.format(
- payload=payload, filename=filename
- )
+ """.format(payload=payload, filename=filename)
)
display(javas)
diff --git a/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_q_planes_widgets.py b/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_q_planes_widgets.py
index fc72baf..c54199c 100644
--- a/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_q_planes_widgets.py
+++ b/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_q_planes_widgets.py
@@ -1,18 +1,31 @@
+import ipywidgets as ipw
+import base64
+import json
+import numpy as np
+import plotly.io as pio
+
+from IPython.display import display
+
from euphonic.cli.utils import (
- _bands_from_force_constants,
- _calc_modes_kwargs,
- _compose_style,
- _plot_label_kwargs,
- get_args,
_get_debye_waller,
_get_energy_bins,
- _get_q_distance,
- _get_cli_parser,
- load_data_from_file,
- matplotlib_save_or_show,
)
-from aiidalab_qe_vibroscopy.utils.euphonic.euphonic_base_widgets import *
+from aiidalab_qe_vibroscopy.utils.euphonic.euphonic_base_widgets import (
+ StructureFactorSettingsBaseWidget,
+ COLORSCALE,
+ COLORBAR_DICT,
+ StructureFactorBasePlotWidget,
+)
+
+from monty.json import jsanitize
+import plotly.graph_objects as go
+
+from aiidalab_qe_vibroscopy.utils.euphonic.intensity_maps import (
+ blockPrint,
+ enablePrint,
+ AttrDict,
+)
def produce_Q_section_modes(
@@ -26,12 +39,7 @@ def produce_Q_section_modes(
k_extension=1,
temperature=0,
):
-
from euphonic import ureg
- from aiidalab_qe_vibroscopy.utils.euphonic.intensity_maps import (
- blockPrint,
- enablePrint,
- )
# see get_Q_section
# h: array vector
@@ -94,7 +102,6 @@ def produce_Q_section_spectrum(
dw=None,
labels=None,
):
-
from aiidalab_qe_vibroscopy.utils.euphonic.intensity_maps import (
blockPrint,
enablePrint,
@@ -117,9 +124,9 @@ def produce_Q_section_spectrum(
sigma = (deltaE) / 2
# Gaussian weights.
- weights = np.exp(
- -((spectrum.y_data.magnitude - mu) ** 2) / 2 * sigma**2
- ) / np.sqrt(2 * np.pi * sigma**2)
+ weights = np.exp(-((spectrum.y_data.magnitude - mu) ** 2) / 2 * sigma**2) / np.sqrt(
+ 2 * np.pi * sigma**2
+ )
av_spec = np.average(spectrum.z_data.magnitude, axis=1, weights=weights[:-1])
enablePrint()
@@ -128,7 +135,6 @@ def produce_Q_section_spectrum(
class QSectionPlotWidget(StructureFactorBasePlotWidget):
def __init__(self, h_array, k_array, av_spec, labels, intensity_ref_0K=1, **kwargs):
-
self.intensity_ref_0K = intensity_ref_0K
self.fig = go.FigureWidget()
@@ -174,7 +180,6 @@ def _update_spectra(
av_spec,
labels,
):
-
# If I do this
# self.data = ()
# I have a delay in the plotting, I have blank plot while it
@@ -213,7 +218,6 @@ def _update_spectra(
class QSectionSettingsWidget(StructureFactorSettingsBaseWidget):
def __init__(self, **kwargs):
-
super().__init__()
self.float_ecenter = ipw.FloatText(
@@ -351,7 +355,6 @@ class QSectionFullWidget(ipw.VBox):
"""
def __init__(self, fc, intensity_ref_0K=1, **kwargs):
-
self.fc = fc
self.title_intensity = ipw.HTML(
@@ -502,8 +505,6 @@ def _download(payload, filename):
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
- """.format(
- payload=payload, filename=filename
- )
+ """.format(payload=payload, filename=filename)
)
display(javas)
diff --git a/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_single_crystal_widgets.py b/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_single_crystal_widgets.py
index d78a42d..1437772 100644
--- a/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_single_crystal_widgets.py
+++ b/src/aiidalab_qe_vibroscopy/utils/euphonic/euphonic_single_crystal_widgets.py
@@ -1,33 +1,33 @@
-import pathlib
-import tempfile
-import io
-
import base64
-from IPython.display import HTML, clear_output, display
-
-import euphonic
-from phonopy.file_IO import write_force_constants_to_hdf5, write_disp_yaml
+from IPython.display import display
+import numpy as np
import ipywidgets as ipw
import plotly.graph_objects as go
import plotly.io as pio
# from ..euphonic.bands_pdos import *
-from ..euphonic.intensity_maps import *
+from ..euphonic.intensity_maps import (
+ AttrDict,
+ produce_bands_weigthed_data,
+ generated_curated_data,
+)
import json
from monty.json import jsanitize
# sys and os used to prevent euphonic to print in the stdout.
-import sys
-import os
-from aiidalab_qe_vibroscopy.utils.euphonic.euphonic_base_widgets import *
+from aiidalab_qe_vibroscopy.utils.euphonic.euphonic_base_widgets import (
+ StructureFactorSettingsBaseWidget,
+ COLORSCALE,
+ COLORBAR_DICT,
+ StructureFactorBasePlotWidget,
+)
class SingleCrystalPlotWidget(StructureFactorBasePlotWidget):
def __init__(self, spectra, intensity_ref_0K=1, **kwargs):
-
(
final_xspectra,
final_zspectra,
@@ -71,7 +71,6 @@ def __init__(self, spectra, intensity_ref_0K=1, **kwargs):
)
def _update_spectra(self, spectra):
-
(
final_xspectra,
final_zspectra,
@@ -91,9 +90,11 @@ def _update_spectra(self, spectra):
self.fig.add_trace(
go.Heatmap(
z=final_zspectra.T,
- y=y[:, 0] * self.THz_to_meV
- if self.E_units_button.value == "meV"
- else y[:, 0],
+ y=(
+ y[:, 0] * self.THz_to_meV
+ if self.E_units_button.value == "meV"
+ else y[:, 0]
+ ),
x=x,
colorbar=COLORBAR_DICT,
colorscale=COLORSCALE, # imported from euphonic_base_widgets
@@ -115,7 +116,6 @@ def _update_spectra(self, spectra):
class SingleCrystalSettingsWidget(StructureFactorSettingsBaseWidget):
def __init__(self, **kwargs):
-
self.custom_kpath_description = ipw.HTML(
"""
@@ -197,11 +197,11 @@ class SingleCrystalFullWidget(ipw.VBox):
"""
def __init__(self, fc, **kwargs):
-
self.fc = fc
self.spectra, self.parameters = produce_bands_weigthed_data(
- fc=self.fc, plot=False # CHANGED
+ fc=self.fc,
+ plot=False, # CHANGED
)
self.title_intensity = ipw.HTML(
@@ -316,7 +316,7 @@ def curate_path_and_labels(
for k in s:
labels.append(k.strip())
# AAA missing support for fractions.
- l = tuple(map(float, [kk for kk in k.strip().split(" ")]))
+ l = tuple(map(float, [kk for kk in k.strip().split(" ")])) # noqa: E741
scoords.append(l)
coordinates.append(scoords)
return coordinates, labels
@@ -333,8 +333,6 @@ def _download(payload, filename):
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
- """.format(
- payload=payload, filename=filename
- )
+ """.format(payload=payload, filename=filename)
)
display(javas)
diff --git a/src/aiidalab_qe_vibroscopy/utils/euphonic/intensity_maps.py b/src/aiidalab_qe_vibroscopy/utils/euphonic/intensity_maps.py
index 409e322..0bc1a0e 100644
--- a/src/aiidalab_qe_vibroscopy/utils/euphonic/intensity_maps.py
+++ b/src/aiidalab_qe_vibroscopy/utils/euphonic/intensity_maps.py
@@ -1,4 +1,3 @@
-from argparse import ArgumentParser
from typing import List, Optional
import pathlib
@@ -15,7 +14,7 @@
Check double imports!
"""
import euphonic
-from euphonic import ureg, Spectrum2D, QpointFrequencies, ForceConstants
+from euphonic import ureg, QpointFrequencies, ForceConstants
import euphonic.plot
from euphonic.util import get_qpoint_labels
from euphonic.styles import base_style
@@ -24,38 +23,26 @@
_calc_modes_kwargs,
_compose_style,
_plot_label_kwargs,
- get_args,
_get_debye_waller,
_get_energy_bins,
_get_q_distance,
- _get_cli_parser,
- load_data_from_file,
matplotlib_save_or_show,
)
from euphonic.cli.utils import (
- _calc_modes_kwargs,
- _compose_style,
- _get_cli_parser,
- _get_debye_waller,
- _get_energy_bins,
- _get_q_distance,
_get_pdos_weighting,
_arrange_pdos_groups,
- _plot_label_kwargs,
)
-from euphonic.cli.utils import load_data_from_file, get_args, matplotlib_save_or_show
-import euphonic.plot
from euphonic.powder import (
sample_sphere_dos,
sample_sphere_pdos,
sample_sphere_structure_factor,
)
from euphonic.spectra import apply_kinematic_constraints
-from euphonic.styles import base_style, intensity_widget_style
+from euphonic.styles import intensity_widget_style
import euphonic.util
-from phonopy.file_IO import write_force_constants_to_hdf5, write_disp_yaml
+from phonopy.file_IO import write_force_constants_to_hdf5
# Dummy tqdm function if tqdm progress bars unavailable
try:
@@ -69,7 +56,9 @@ def tqdm(sequence):
return sequence
-import sys, os
+import sys
+import os
+
# Disable
def blockPrint():
@@ -130,9 +119,7 @@ def join_q_paths(coordinates: list, labels: list, delta_q=0.1, G=[0, 0, 0]):
list_of_paths = []
Nq_tot = 0
- new_labels_index = (
- []
- ) # here we store the index to then set the labels list as in seekpath, to be refined in the produce_curated_data routine.
+ new_labels_index = [] # here we store the index to then set the labels list as in seekpath, to be refined in the produce_curated_data routine.
for path in coordinates:
kxi, kyi, kzi = path[0] # starting point
kxf, kyf, kzf = path[1] # end point
@@ -273,7 +260,6 @@ def produce_bands_weigthed_data(
# print("Getting band path...")
# HERE we add the custom path generation:
if linear_path:
-
# 1. get the rl_norm list for conversion delta_q ==> Nq in the join_q_paths
structure = fc.crystal.to_spglib_cell()
bandpath = seekpath.get_explicit_k_path(structure)
@@ -365,10 +351,12 @@ def produce_bands_weigthed_data(
style = _compose_style(user_args=args, base=[base_style])
if plot:
with matplotlib.style.context(style):
-
- fig = euphonic.plot.plot_2d(
- spectra, vmin=args.vmin, vmax=args.vmax, **plot_label_kwargs
- )
+ fig = euphonic.plot.plot_2d( # noqa F841
+ spectra, # noqa F841
+ vmin=args.vmin, # noqa F841
+ vmax=args.vmax, # noqa F841
+ **plot_label_kwargs, # noqa F841
+ ) # noqa F841
matplotlib_save_or_show(save_filename=args.save_to)
enablePrint()
@@ -756,12 +744,11 @@ def generate_force_constant_instance(
def export_euphonic_data(node, fermi_energy=None):
-
- if not "vibronic" in node.outputs:
+ if "vibronic" not in node.outputs:
# Not a phonon calculation
return None
else:
- if not "phonon_bands" in node.outputs.vibronic:
+ if "phonon_bands" not in node.outputs.vibronic:
return None
output_set = node.outputs.vibronic.phonon_bands
@@ -802,7 +789,6 @@ def generated_curated_data(spectra):
if len(ticks_positions) > 1:
if ticks_positions[-1] < ticks_positions[-2] or shift:
if ticks_positions[-1] == 0: # new linear path
-
ticks_positions.pop()
last = ticks_labels.pop().strip()
diff --git a/src/aiidalab_qe_vibroscopy/utils/harmonic/__init__.py b/src/aiidalab_qe_vibroscopy/utils/harmonic/__init__.py
deleted file mode 100644
index e8959e0..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/harmonic/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# from aiidalab_qe_vibroscopy.harmonic.settings import Setting
-# from aiidalab_qe_vibroscopy.harmonic.workchain import workchain_and_builder
-# from aiidalab_qe_vibroscopy.harmonic.result import Result
-from aiidalab_qe.common.panel import OutlinePanel
-
-
-class Outline(OutlinePanel):
- title = "Phonon properties"
- # description = "Select to proceed with the calculation of the phononic and dielectric properties"
-
-
-property = {
- "outline": Outline,
- # "setting": Setting,
- # "workchain": workchain_and_builder,
- # "result": Result,
-}
diff --git a/src/aiidalab_qe_vibroscopy/utils/harmonic/result.py b/src/aiidalab_qe_vibroscopy/utils/harmonic/result.py
deleted file mode 100644
index 5557803..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/harmonic/result.py
+++ /dev/null
@@ -1,178 +0,0 @@
-"""Bands results view widgets
-
-"""
-
-
-
-from aiidalab_qe.common.panel import ResultPanel
-
-import numpy as np
-
-
-def export_phononworkchain_data(node, fermi_energy=None):
-
- """
- We have multiple choices: BANDS, DOS, THERMODYNAMIC, FORCES.
- """
-
- import json
-
- from monty.json import jsanitize
-
- parameters = {}
-
- if not "vibronic" in node.outputs:
- return None
- else:
- if (
- not "harmonic" in node.outputs.vibronic
- and not "phonon" in node.outputs.vibronic
- ):
- return None
-
- output_set = (
- node.outputs.vibronic.harmonic
- if "harmonic" in node.outputs.vibronic
- else node.outputs.vibronic.phonon
- )
-
- if "output_phonopy" in output_set:
- if "phonon_bands" in output_set.output_phonopy:
- data = json.loads(
- output_set.output_phonopy.phonon_bands._exportcontent(
- "json", comments=False
- )[0]
- )
- # The fermi energy from band calculation is not robust.
- """data["fermi_level"] = (
- fermi_energy or node.outputs.phonons.band_parameters["fermi_energy"]
- )"""
- # to be optimized: use the above results!!!
- bands = output_set.output_phonopy.phonon_bands.get_bands()
- data["fermi_level"] = 0
- data["Y_label"] = "Dispersion (THz)"
-
- # it does work now.
- parameters["energy_range"] = {
- "ymin": np.min(bands) - 0.1,
- "ymax": np.max(bands) + 0.1,
- }
-
- # TODO: THERMOD, FORCES; minors: bands-labels, done: no-fermi-in-dos.
-
- return [jsanitize(data), parameters, "bands"]
- elif "total_phonon_dos" in output_set.output_phonopy:
- (
- what,
- energy_dos,
- units_omega,
- ) = output_set.output_phonopy.total_phonon_dos.get_x()
- (
- dos_name,
- dos_data,
- units_dos,
- ) = output_set.output_phonopy.total_phonon_dos.get_y()[0]
- dos = []
- # The total dos parsed
- tdos = {
- "label": "Total DOS",
- "x": energy_dos.tolist(),
- "y": dos_data.tolist(),
- "borderColor": "#8A8A8A", # dark gray
- "backgroundColor": "#8A8A8A", # light gray
- "backgroundAlpha": "40%",
- "lineStyle": "solid",
- }
- dos.append(tdos)
-
- parameters["energy_range"] = {
- "ymin": np.min(energy_dos) - 0.1,
- "ymax": np.max(energy_dos) + 0.1,
- }
-
- data_dict = {
- "fermi_energy": 0, # I do not want it in my plot
- "dos": dos,
- }
-
- return [json.loads(json.dumps(data_dict)), parameters, "dos"]
- elif "thermal_properties" in output_set.output_phonopy:
- what, T, units_k = output_set.output_phonopy.thermal_properties.get_x()
- (
- F_name,
- F_data,
- units_F,
- ) = output_set.output_phonopy.thermal_properties.get_y()[0]
- (
- Entropy_name,
- Entropy_data,
- units_entropy,
- ) = output_set.output_phonopy.thermal_properties.get_y()[1]
- (
- Cv_name,
- Cv_data,
- units_Cv,
- ) = output_set.output_phonopy.thermal_properties.get_y()[2]
-
- return (
- [T, F_data, units_F, Entropy_data, units_entropy, Cv_data, units_Cv],
- [],
- "thermal",
- )
-
- else:
- return None
-
-
-class Result(ResultPanel):
-
- title = "Phonon property"
- workchain_label = "phonons"
-
- def _update_view(self):
- bands_data = export_phononworkchain_data(self.node)
-
- if bands_data[2] == "bands":
- _bands_plot_view = BandsPlotWidget(
- bands=[bands_data[0]],
- **bands_data[1],
- )
- self.children = [
- _bands_plot_view,
- ]
- elif bands_data[2] == "dos":
- _bands_plot_view = BandsPlotWidget(
- dos=bands_data[0],
- plot_fermilevel=False,
- show_legend=False,
- **bands_data[1],
- )
- self.children = [
- _bands_plot_view,
- ]
-
- elif bands_data[2] == "thermal":
- import plotly.graph_objects as go
-
- T = bands_data[0][0]
- F = bands_data[0][1]
- F_units = bands_data[0][2]
- E = bands_data[0][3]
- E_units = bands_data[0][4]
- Cv = bands_data[0][5]
- Cv_units = bands_data[0][6]
-
- g = go.FigureWidget(
- layout=go.Layout(
- title=dict(text="Thermal properties"),
- barmode="overlay",
- )
- )
- g.layout.xaxis.title = "Temperature (K)"
- 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})")
-
- self.children = [
- g,
- ]
diff --git a/src/aiidalab_qe_vibroscopy/utils/harmonic/settings.py b/src/aiidalab_qe_vibroscopy/utils/harmonic/settings.py
deleted file mode 100644
index de4209c..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/harmonic/settings.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Panel for PhononWorkchain plugin.
-
-Authors:
-
- * Miki Bonacci
- Inspired by Xing Wang
-"""
-import ipywidgets as ipw
-from aiida.orm import Float, Int, Str
-
-from aiidalab_qe.common.panel import Panel
-
-
-class Setting(Panel):
- title = "Phonons Settings"
- identifier = "harmonic"
-
- def __init__(self, **kwargs):
- self.settings_title = ipw.HTML(
- """
-
Phonons settings
"""
- )
- self.settings_help = ipw.HTML(
- """
- Please select the phonon-related properties to be computed in this simulation.
- You can select also the size of the supercell to be used; usually, a 2X2X2 supercell is enough
- to obtain converged results.
-
"""
- )
-
- self.polar_help = ipw.HTML(
- """
- If the material is polar, also 3rd order derivatives will be computed and more
- accurate phonon band interpolation is performed.
-
"""
- )
-
- self.workchain_protocol = ipw.ToggleButtons(
- options=["fast", "moderate", "precise"],
- value="moderate",
- )
-
- # I want to be able to select more than only one... this has to change at the PhononWorkChain level.
- self.phonon_property = ipw.Dropdown(
- options=[
- ["band structure", "BANDS"],
- ["density of states (DOS)", "DOS"],
- ["thermal properties", "THERMODYNAMIC"],
- ["force constants", "NONE"],
- ["none", "none"],
- ],
- value="BANDS",
- description="Phonon property:",
- disabled=False,
- style={"description_width": "initial"},
- )
-
- # 1. Supercell
- self.supercell = [1, 1, 1]
-
- def change_supercell(_=None):
- self.supercell = [
- _supercell[0].value,
- _supercell[1].value,
- _supercell[2].value,
- ]
-
- _supercell = [
- ipw.BoundedIntText(value=1, min=1, layout={"width": "40px"}),
- ipw.BoundedIntText(value=1, min=1, layout={"width": "40px"}),
- ipw.BoundedIntText(value=1, min=1, layout={"width": "40px"}),
- ]
- for elem in _supercell:
- elem.observe(change_supercell, names="value")
- self.supercell_selector = ipw.HBox(
- children=[
- ipw.HTML(
- description="Supercell size:",
- style={"description_width": "initial"},
- )
- ]
- + _supercell,
- )
-
- self.dielectric_property = ipw.Dropdown(
- options=[
- ["dielectric tensor", "dielectric"],
- #'ir',
- #'raman',
- #'born-charges',
- #'nac',
- #'bec',
- #'susceptibility-derivative',
- #'non-linear-susceptibility',
- ["none", "none"],
- ],
- value="none",
- description="Dielectric property:",
- disabled=False,
- style={"description_width": "initial"},
- )
-
- # to trigger Dielectric property = Raman... FOR POLAR MATERIALS.
- self.material_is_polar = ipw.ToggleButtons(
- options=[("Off", "off"), ("On", "on")],
- value="off",
- style={"description_width": "initial"},
- )
-
- self.children = [
- self.settings_title,
- self.settings_help,
- ipw.HBox(
- children=[
- self.phonon_property,
- self.supercell_selector,
- ],
- layout=ipw.Layout(justify_content="flex-start"),
- ),
- self.dielectric_property,
- self.polar_help,
- ipw.HBox(
- children=[
- ipw.Label(
- "Material is polar:",
- layout=ipw.Layout(justify_content="flex-start", width="120px"),
- ),
- self.material_is_polar,
- ]
- ),
- ]
- super().__init__(**kwargs)
-
- def get_panel_value(self):
- """Return a dictionary with the input parameters for the plugin."""
- if isinstance(self.phonon_property, str):
- return {
- "phonon_property": self.phonon_property,
- "dielectric_property": self.dielectric_property,
- "material_is_polar": self.material_is_polar,
- "supercell_selector": self.supercell,
- }
- return {
- "phonon_property": self.phonon_property.value,
- "dielectric_property": self.dielectric_property.value,
- "material_is_polar": self.material_is_polar.value,
- "supercell_selector": self.supercell,
- }
-
- def load_panel_value(self, input_dict):
- """Load a dictionary with the input parameters for the plugin."""
- self.phonon_property.value = input_dict.get("phonon_property", "NONE")
- self.dielectric_property.value = input_dict.get("dielectric_property", "none")
- self.material_is_polar.value = input_dict.get("material_is_polar", "off")
- self.supercell = input_dict.get("supercell_selector", [1, 1, 1])
diff --git a/src/aiidalab_qe_vibroscopy/utils/harmonic/workchain.py b/src/aiidalab_qe_vibroscopy/utils/harmonic/workchain.py
deleted file mode 100644
index 5ae8f5d..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/harmonic/workchain.py
+++ /dev/null
@@ -1,114 +0,0 @@
-from aiida.orm import load_code, Dict
-from aiida.plugins import WorkflowFactory
-from aiida_quantumespresso.common.types import ElectronicType, SpinType
-
-from aiida_vibroscopy.common.properties import PhononProperty
-
-HarmonicWorkChain = WorkflowFactory("vibroscopy.phonons.harmonic")
-
-"""
-The logic is that HarmonicWorkchain can run PhononWorkchain and DielectricWorkchain, skipping the second
-but not the firstfor now we do not support to run only DielectricWorkchain.
-"""
-
-
-def get_builder(codes, structure, parameters):
- from copy import deepcopy
-
- protocol = parameters["workchain"].pop("protocol", "fast")
- pw_code = codes.get("pw")
- phonopy_code = codes.get("phonopy")
- phonon_property = PhononProperty[
- parameters["harmonic"].pop("phonon_property", "none")
- ]
- supercell_matrix = parameters["harmonic"].pop("supercell_selector", None)
- dielectric_property = parameters["harmonic"].pop("dielectric_property", "none")
- polar = parameters["harmonic"].pop("material_is_polar", "off")
-
- if polar == "on":
- dielectric_property = "raman"
-
- scf_overrides = deepcopy(parameters["advanced"])
- overrides = {
- "phonon": {
- "scf": scf_overrides,
- "supercell_matrix": supercell_matrix,
- },
- "dielectric": {"scf": scf_overrides, "property": dielectric_property},
- }
-
- builder = HarmonicWorkChain.get_builder_from_protocol(
- pw_code=pw_code,
- phonopy_code=phonopy_code,
- structure=structure,
- protocol=protocol,
- overrides=overrides,
- phonon_property=phonon_property,
- electronic_type=ElectronicType(parameters["workchain"]["electronic_type"]),
- spin_type=SpinType(parameters["workchain"]["spin_type"]),
- initial_magnetic_moments=parameters["advanced"]["initial_magnetic_moments"],
- )
-
- # MB supposes phonopy will always run serially, otherwise choose phono3py
- # also this is needed to be set here.
- builder.phonopy.metadata.options.resources = {
- "num_machines": 1,
- "num_mpiprocs_per_machine": 1,
- }
-
- builder.phonon.phonopy.metadata.options.resources = (
- builder.phonopy.metadata.options.resources
- )
-
- # should be automatic inside HarmonicWorkchain.
- builder.phonon.phonopy.parameters = Dict(dict={})
- builder.phonopy.parameters = builder.phonon.phonopy.parameters
- builder.phonon.phonopy.code = builder.phonopy.code
-
- builder.phonopy.parameters = Dict(dict=phonon_property.value)
-
- return builder
-
-
-def trigger_workchain(name, parameters):
- if name not in ["harmonic", "phonons", "dielectric", "iraman"]:
- return True
- import copy
-
- parameters_ = copy.deepcopy(parameters)
- harmonic_params = parameters_.pop("harmonic", {})
- phonon_property = harmonic_params.pop("phonon_property", "none")
- dielectric_property = harmonic_params.pop("dielectric_property", "none")
- polar = harmonic_params.pop("material_is_polar", "off")
-
- trigger_spectrum = parameters_.pop("iraman", {}).pop("spectrum", False)
-
- trigger_harmonic = (
- polar == "on" or (phonon_property != "none" and dielectric_property != "none")
- ) and not trigger_spectrum
- trigger_phonons = (
- phonon_property != "none"
- and dielectric_property == "none"
- and not trigger_harmonic
- ) and not trigger_spectrum
- trigger_dielectric = (
- phonon_property == "none"
- and dielectric_property != "none"
- and not trigger_harmonic
- ) and not trigger_spectrum
-
- trigger = {
- "iraman": trigger_spectrum,
- "harmonic": trigger_harmonic,
- "phonons": trigger_phonons,
- "dielectric": trigger_dielectric,
- }
-
- return trigger[name]
-
-
-workchain_and_builder = {
- "workchain": HarmonicWorkChain,
- "exclude": ("clean_workdir",),
- "get_builder": get_builder,
-}
diff --git a/src/aiidalab_qe_vibroscopy/utils/phonons/__init__.py b/src/aiidalab_qe_vibroscopy/utils/phonons/__init__.py
deleted file mode 100644
index 4fa0bfe..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/phonons/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# from aiidalab_qe_vibroscopy.phonons.settings import Setting
-# from aiidalab_qe_vibroscopy.phonons.workchain import workchain_and_builder
-# from aiidalab_qe_vibroscopy.phonons.result import Result
-from aiidalab_qe.common.panel import OutlinePanel
-import ipywidgets as ipw
-
-
-class Outline(OutlinePanel):
- title = "Phonon band structure"
- help = "Harmonic approximation"
-
- def __init__(self, **kwargs):
- super().__init__(**kwargs)
- self.layout = ipw.Layout(width="600px", display="none")
-
-
-property = {
- "outline": Outline,
- # "setting": Setting,
- # "workchain": workchain_and_builder,
- # "result": Result,
-}
diff --git a/src/aiidalab_qe_vibroscopy/utils/phonons/result.py b/src/aiidalab_qe_vibroscopy/utils/phonons/result.py
index 8d7e5c3..534cc50 100644
--- a/src/aiidalab_qe_vibroscopy/utils/phonons/result.py
+++ b/src/aiidalab_qe_vibroscopy/utils/phonons/result.py
@@ -1,6 +1,4 @@
-"""Bands results view widgets
-
-"""
+"""Bands results view widgets"""
from aiidalab_qe.common.bandpdoswidget import cmap, get_bands_labeling
@@ -11,10 +9,10 @@
def replace_symbols_with_uppercase(data):
symbols_mapping = {
"$\Gamma$": "\u0393",
- "$\\Gamma$": "\u0393",
+ "$\\Gamma$": "\u0393", # noqa: F601
"$\\Delta$": "\u0394",
- "$\\Lambda$": "\u039B",
- "$\\Sigma$": "\u03A3",
+ "$\\Lambda$": "\u039b",
+ "$\\Sigma$": "\u03a3",
"$\\Epsilon$": "\u0395",
}
@@ -25,15 +23,10 @@ def replace_symbols_with_uppercase(data):
def export_phononworkchain_data(node, fermi_energy=None):
-
"""
We have multiple choices: BANDS, DOS, THERMODYNAMIC.
"""
- import json
-
- from monty.json import jsanitize
-
full_data = {
"bands": None,
"pdos": None,
@@ -41,11 +34,10 @@ def export_phononworkchain_data(node, fermi_energy=None):
}
parameters = {}
- if not "vibronic" in node.outputs:
+ if "vibronic" not in node.outputs:
return None
if "phonon_bands" in node.outputs.vibronic:
-
"""
copied and pasted from aiidalab_qe.common.bandsplotwidget.
adapted for phonon outputs
@@ -60,7 +52,9 @@ def export_phononworkchain_data(node, fermi_energy=None):
replace_symbols_with_uppercase(data["pathlabels"])
data["Y_label"] = "Dispersion (THz)"
- bands = node.outputs.vibronic.phonon_bands._get_bandplot_data(cartesian=True, prettify_format=None, join_symbol=None, get_segments=True)
+ bands = node.outputs.vibronic.phonon_bands._get_bandplot_data(
+ cartesian=True, prettify_format=None, join_symbol=None, get_segments=True
+ )
parameters["energy_range"] = {
"ymin": np.min(bands["y"]) - 0.1,
"ymax": np.max(bands["y"]) + 0.1,
@@ -71,7 +65,6 @@ def export_phononworkchain_data(node, fermi_energy=None):
full_data["bands"] = [data, parameters]
if "phonon_pdos" in node.outputs.vibronic:
-
phonopy_calc = node.outputs.vibronic.phonon_pdos.creator
kwargs = {}
@@ -84,9 +77,10 @@ def export_phononworkchain_data(node, fermi_energy=None):
symbols = node.inputs.structure.get_ase().get_chemical_symbols()
pdos = node.outputs.vibronic.phonon_pdos
- index_dict, dos_dict = {}, {
- "total_dos": np.zeros(np.shape(pdos.get_y()[0][1]))
- }
+ index_dict, dos_dict = (
+ {},
+ {"total_dos": np.zeros(np.shape(pdos.get_y()[0][1]))},
+ )
for atom in set(symbols):
# index lists
index_dict[atom] = [
diff --git a/src/aiidalab_qe_vibroscopy/utils/phonons/settings.py b/src/aiidalab_qe_vibroscopy/utils/phonons/settings.py
deleted file mode 100644
index a8d759b..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/phonons/settings.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Setting Panel for PhononWorkchain plugin.
-
-Authors:
-
- * Miki Bonacci
- Inspired by Xing Wang
-"""
-import ipywidgets as ipw
-
-from aiidalab_qe.common.panel import Panel
-from aiida_vibroscopy.common.properties import PhononProperty
-
-
-class Setting(Panel):
- title = "Phonons Settings"
- identifier = "phonons"
-
- def __init__(self, **kwargs):
- self.settings_title = ipw.HTML(
- """
-
Phonons settings
"""
- )
- self.settings_help = ipw.HTML(
- """
- Please select the phonon-related properties to be computed in the simulation.
- If the material is polar, also 3rd order derivatives will be computed and more
- accurate phonon band interpolation is done.
-
"""
- )
- self.workchain_protocol = ipw.ToggleButtons(
- options=["fast", "moderate", "precise"],
- value="moderate",
- )
-
- # I want to be able to select more than only one... this has to change at the PhononWorkChain level.
- self.phonon_property = ipw.Dropdown(
- options=[
- ["bands", "BANDS"],
- ["dos", "DOS"],
- ["thermodynamic", "THERMODYNAMIC"],
- ["force constants", "NONE"],
- ],
- value="BANDS",
- description="Phonon property:",
- disabled=False,
- style={"description_width": "initial"},
- )
-
- self.children = [
- self.settings_title,
- self.settings_help,
- self.phonon_property,
- ]
- super().__init__(**kwargs)
-
- def get_panel_value(self):
- """Return a dictionary with the input parameters for the plugin."""
- if isinstance(self.phonon_property, str):
- return {
- "phonon_property": self.phonon_property,
- }
- return {
- "phonon_property": self.phonon_property.value,
- }
-
- def load_panel_value(self, input_dict):
- """Load a dictionary with the input parameters for the plugin."""
- self.phonon_property.value = input_dict.get("phonon_property", "BANDS")
diff --git a/src/aiidalab_qe_vibroscopy/utils/phonons/workchain.py b/src/aiidalab_qe_vibroscopy/utils/phonons/workchain.py
deleted file mode 100644
index ba71add..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/phonons/workchain.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from aiida.orm import load_code
-from aiida.plugins import WorkflowFactory
-from aiida_quantumespresso.common.types import ElectronicType, SpinType
-from aiida_vibroscopy.common.properties import PhononProperty
-
-PhononWorkChain = WorkflowFactory("vibroscopy.phonons.phonon")
-
-
-def get_builder(codes, structure, parameters):
- from copy import deepcopy
-
- pw_code = codes.get("pw")
- phonopy_code = codes.get("phonopy", None)
- phonon_property = PhononProperty[
- parameters["harmonic"].pop("phonon_property", "none")
- ]
- supercell_matrix = parameters["harmonic"].pop("supercell_selector", None)
- protocol = parameters["workchain"].pop("protocol", "fast")
- scf_overrides = deepcopy(parameters["advanced"])
- overrides = {
- "scf": scf_overrides,
- "supercell_matrix": supercell_matrix,
- }
-
- builder = PhononWorkChain.get_builder_from_protocol(
- pw_code=pw_code,
- phonopy_code=phonopy_code,
- structure=structure,
- protocol=protocol,
- overrides=overrides,
- phonon_property=phonon_property,
- electronic_type=ElectronicType(parameters["workchain"]["electronic_type"]),
- spin_type=SpinType(parameters["workchain"]["spin_type"]),
- initial_magnetic_moments=parameters["advanced"]["initial_magnetic_moments"],
- )
-
- # MB supposes phonopy will always run serially, otherwise choose phono3py
- # also this is needed to be set here.
- builder.phonopy.metadata.options.resources = {
- "num_machines": 1,
- "num_mpiprocs_per_machine": 1,
- }
-
- return builder
-
-
-workchain_and_builder = {
- "workchain": PhononWorkChain,
- "exclude": ("clean_workdir",),
- "get_builder": get_builder,
-}
diff --git a/src/aiidalab_qe_vibroscopy/utils/raman/__init__.py b/src/aiidalab_qe_vibroscopy/utils/raman/__init__.py
deleted file mode 100644
index 8aa2b69..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/raman/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# from aiidalab_qe_vibroscopy.raman.settings import Setting
-# from aiidalab_qe_vibroscopy.raman.workchain import workchain_and_builder
-# from aiidalab_qe_vibroscopy.raman.result import Result
-from aiidalab_qe.common.panel import OutlinePanel
-
-
-class Outline(OutlinePanel):
- title = "Vibrational spectra"
- # description = "IR and Raman spectra; you may also select phononic and dielectric properties"
-
-
-property = {
- "outline": Outline,
- # "setting": Setting,
- # "workchain": workchain_and_builder,
- # "result": Result,
-}
diff --git a/src/aiidalab_qe_vibroscopy/utils/raman/result.py b/src/aiidalab_qe_vibroscopy/utils/raman/result.py
index c074735..029eaf2 100644
--- a/src/aiidalab_qe_vibroscopy/utils/raman/result.py
+++ b/src/aiidalab_qe_vibroscopy/utils/raman/result.py
@@ -1,16 +1,13 @@
-"""Bands results view widgets
+"""Bands results view widgets"""
-"""
from __future__ import annotations
-from aiidalab_qe.common.panel import ResultPanel
import ipywidgets as ipw
import numpy as np
from IPython.display import HTML, clear_output, display
import base64
import json
-from ase.visualize import view
import nglview as nv
from ase import Atoms
@@ -26,7 +23,6 @@ def plot_powder(
broadening_function=multilorentz,
normalize: bool = True,
):
-
frequencies = np.array(frequencies)
intensities = np.array(intensities)
@@ -44,12 +40,11 @@ def plot_powder(
def export_iramanworkchain_data(node):
-
"""
We have multiple choices: IR, RAMAN.
"""
- if not "vibronic" in node.outputs:
+ if "vibronic" not in node.outputs:
return None
else:
if "iraman" in node.outputs.vibronic:
@@ -61,7 +56,6 @@ def export_iramanworkchain_data(node):
return None
if "vibrational_data" in output_node:
-
# We enable the possibility to provide both spectra.
# We give as output or string, or the output node.
@@ -87,14 +81,13 @@ def export_iramanworkchain_data(node):
# sometimes IR/Raman has not active peaks by symmetry, or due to the fact that 1st order cannot capture them
if len(total_intensities) == 0:
- spectra_data[
- "Ir"
- ] = "No IR modes detected." # explanation added in the main results script of the app.
+ spectra_data["Ir"] = (
+ "No IR modes detected." # explanation added in the main results script of the app.
+ )
else:
spectra_data["Ir"] = output_node
if "raman_tensors" in vibro.get_arraynames():
-
(
polarized_intensities,
depolarized_intensities,
@@ -105,9 +98,9 @@ def export_iramanworkchain_data(node):
# sometimes IR/Raman has not active peaks by symmetry, or due to the fact that 1st order cannot capture them
if len(total_intensities) == 0:
- spectra_data[
- "Raman"
- ] = "No Raman modes detected." # explanation added in the main results script of the app.
+ spectra_data["Raman"] = (
+ "No Raman modes detected." # explanation added in the main results script of the app.
+ )
else:
spectra_data["Raman"] = output_node
@@ -246,9 +239,7 @@ def _download(payload, filename):
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
- """.format(
- payload=payload, filename=filename
- )
+ """.format(payload=payload, filename=filename)
)
display(javas)
@@ -289,7 +280,9 @@ def _on_plot_button_clicked(self, change):
total_intensities = polarized_intensities
self.frequencies, self.intensities = plot_powder(
- frequencies, total_intensities, self.broadening.value,
+ frequencies,
+ total_intensities,
+ self.broadening.value,
)
self._display_figure()
@@ -340,7 +333,7 @@ def _check_inputs_correct(self, polarization):
try:
dir_values = [float(i) for i in input_values]
return dir_values, True
- except:
+ except: # noqa: E722
return dir_values, False
else:
return dir_values, False
@@ -357,7 +350,7 @@ def _spectrum_widget(self):
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.add_scatter(x=self.frequencies, y=self.intensities, name="")
fig.update_layout(
height=500,
width=700,
diff --git a/src/aiidalab_qe_vibroscopy/utils/raman/settings.py b/src/aiidalab_qe_vibroscopy/utils/raman/settings.py
deleted file mode 100644
index 4d1b907..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/raman/settings.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Panel for PhononWorkchain plugin.
-
-Authors:
-
- * Miki Bonacci
- Inspired by Xing Wang
-"""
-import ipywidgets as ipw
-from aiida.orm import Float, Int, Str
-
-from aiidalab_qe.common.panel import Panel
-from aiida_vibroscopy.common.properties import PhononProperty
-
-
-class Setting(Panel):
- title = "Vibrational Settings"
-
- def __init__(self, **kwargs):
- self.settings_title = ipw.HTML(
- """
-
Vibrational spectra settings
"""
- )
- self.settings_help = ipw.HTML(
- """
- Please select the vibrational spectrum to be computed in this simulation.
-
"""
- )
- self.workchain_protocol = ipw.ToggleButtons(
- options=["fast", "moderate", "precise"],
- value="moderate",
- )
-
- self.spectrum = ipw.ToggleButtons(
- options=[("Infrared", "ir"), ("Raman", "raman")],
- value="raman",
- style={"description_width": "initial"},
- )
-
- # 1. Supercell
- self.supercell = [1, 1, 1]
-
- def change_supercell(_=None):
- self.supercell = [
- _supercell[0].value,
- _supercell[1].value,
- _supercell[2].value,
- ]
-
- _supercell = [
- ipw.BoundedIntText(value=1, min=1, layout={"width": "40px"}),
- ipw.BoundedIntText(value=1, min=1, layout={"width": "40px"}),
- ipw.BoundedIntText(value=1, min=1, layout={"width": "40px"}),
- ]
- for elem in _supercell:
- elem.observe(change_supercell, names="value")
- self.supercell_selector = ipw.HBox(
- children=[
- ipw.HTML(
- description="Supercell size:",
- style={"description_width": "initial"},
- )
- ]
- + _supercell,
- )
-
- self.children = [
- self.settings_title,
- self.settings_help,
- ipw.HBox(
- children=[
- ipw.Label(
- "Spectroscopy:",
- layout=ipw.Layout(justify_content="flex-start", width="120px"),
- ),
- self.spectrum,
- ]
- ),
- self.supercell_selector,
- ]
- super().__init__(**kwargs)
-
- def get_panel_value(self):
- """Return a dictionary with the input parameters for the plugin."""
- return {"spectrum": self.spectrum.value, "supercell_selector": self.supercell}
-
- def load_panel_value(self, input_dict):
- """Load a dictionary with the input parameters for the plugin."""
- self.spectrum.value = input_dict.get("spectrum", "raman")
- self.supercell = input_dict.get("supercell_selector", [1, 1, 1])
diff --git a/src/aiidalab_qe_vibroscopy/utils/raman/workchain.py b/src/aiidalab_qe_vibroscopy/utils/raman/workchain.py
deleted file mode 100644
index f001bde..0000000
--- a/src/aiidalab_qe_vibroscopy/utils/raman/workchain.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from aiida.orm import load_code, Dict
-from aiida.plugins import WorkflowFactory
-from aiida_quantumespresso.common.types import ElectronicType, SpinType
-
-IRamanSpectraWorkChain = WorkflowFactory("vibroscopy.spectra.iraman")
-
-
-def get_builder(codes, structure, parameters):
- from copy import deepcopy
-
- protocol = parameters["workchain"].pop("protocol", "fast")
- pw_code = codes.get("pw")
- phonopy_code = codes.get("phonopy")
- supercell_matrix = parameters["iraman"].pop("supercell_selector", None)
- dielectric_property = parameters["iraman"]["spectrum"]
- res = {
- "num_machines": 1,
- "num_mpiprocs_per_machine": 1,
- }
-
- scf_overrides = deepcopy(parameters["advanced"])
- overrides = {
- "phonon": {
- "scf": scf_overrides,
- "supercell_matrix": supercell_matrix,
- },
- "dielectric": {"scf": scf_overrides, "property": dielectric_property},
- }
-
- builder = IRamanSpectraWorkChain.get_builder_from_protocol(
- code=pw_code,
- structure=structure,
- protocol=protocol,
- overrides=overrides,
- electronic_type=ElectronicType(parameters["workchain"]["electronic_type"]),
- spin_type=SpinType(parameters["workchain"]["spin_type"]),
- initial_magnetic_moments=parameters["advanced"]["initial_magnetic_moments"],
- )
-
- builder.dielectric.property = dielectric_property
-
- builder.phonon.phonopy.code = phonopy_code
- builder.phonon.phonopy.metadata.options.resources = res
- builder.phonon.phonopy.parameters = Dict({})
-
- return builder
-
-
-workchain_and_builder = {
- "workchain": IRamanSpectraWorkChain,
- "exclude": ("clean_workdir",),
- "get_builder": get_builder,
-}
diff --git a/src/aiidalab_qe_vibroscopy/workflows/vibroworkchain.py b/src/aiidalab_qe_vibroscopy/workflows/vibroworkchain.py
index 7bc3d29..ee05481 100644
--- a/src/aiidalab_qe_vibroscopy/workflows/vibroworkchain.py
+++ b/src/aiidalab_qe_vibroscopy/workflows/vibroworkchain.py
@@ -1,12 +1,11 @@
"""Implementation of the VibroWorkchain for managing the aiida-vibroscopy workchains."""
+
from aiida import orm
from aiida.common import AttributeDict
-from aiida.engine import ToContext, WorkChain, calcfunction
-from aiida.orm import AbstractCode, Int, Float, Dict, Code, StructureData, load_code
+from aiida.engine import WorkChain
+from aiida.orm import Dict, StructureData
from aiida.plugins import WorkflowFactory, CalculationFactory
-from aiida_quantumespresso.utils.mapping import prepare_process_inputs
-from aiida_quantumespresso.common.types import ElectronicType, SpinType
-from aiida.engine import WorkChain, calcfunction, if_
+from aiida.engine import if_
from aiida_vibroscopy.common.properties import PhononProperty
from aiida_quantumespresso.calculations.functions.create_kpoints_from_distance import (
create_kpoints_from_distance,
@@ -143,7 +142,7 @@ def determine_symmetry_path(structure):
and math.isclose(cell_angles[2], 90.0, abs_tol=tolerance)
): "square",
(
- math.isclose(cell_lengths[0], cell_lengths[1], abs_tol=tolerance) == False
+ not math.isclose(cell_lengths[0], cell_lengths[1], abs_tol=tolerance)
and math.isclose(cell_angles[2], 90.0, abs_tol=tolerance)
): "rectangular",
(
@@ -154,8 +153,8 @@ def determine_symmetry_path(structure):
)
): "rectangular_centered",
(
- math.isclose(cell_lengths[0], cell_lengths[1], abs_tol=tolerance) == False
- and math.isclose(cell_angles[2], 90.0, abs_tol=tolerance) == False
+ not math.isclose(cell_lengths[0], cell_lengths[1], abs_tol=tolerance)
+ and not math.isclose(cell_angles[2], 90.0, abs_tol=tolerance)
): "oblique",
}
@@ -180,6 +179,7 @@ def determine_symmetry_path(structure):
class VibroWorkChain(WorkChain):
"WorkChain to compute vibrational property of a crystal."
+
label = "vibro"
@classmethod
@@ -235,15 +235,17 @@ def define(cls, spec):
},
)
spec.expose_inputs(
- PhonopyCalculation, namespace='phonopy_calc',
+ PhonopyCalculation,
+ namespace="phonopy_calc",
namespace_options={
- 'required': False, 'populate_defaults': False,
- 'help': (
- 'Inputs for the `PhonopyCalculation` that will'
- 'be used to calculate the inter-atomic force constants, or for post-processing.'
- )
+ "required": False,
+ "populate_defaults": False,
+ "help": (
+ "Inputs for the `PhonopyCalculation` that will"
+ "be used to calculate the inter-atomic force constants, or for post-processing."
+ ),
},
- exclude=['phonopy_data', 'force_constants', 'parameters'],
+ exclude=["phonopy_data", "force_constants", "parameters"],
)
spec.input(
"phonopy_bands_dict",
@@ -358,7 +360,6 @@ def get_builder_from_protocol(
sub processes that are called by this workchain.
:return: a process builder instance with all inputs defined ready for launch.
"""
- from aiida_quantumespresso.workflows.protocols.utils import recursive_merge
if simulation_mode not in range(1, 5):
raise ValueError("simulation_mode not in [1,2,3,4]")
@@ -394,8 +395,10 @@ def get_builder_from_protocol(
builder_harmonic.phonopy.parameters = (
builder_harmonic.phonon.phonopy.parameters
)
-
- builder_harmonic.dielectric.scf.pw.code = dielectric_code # we have a specific code for DielectricWorkChain
+
+ builder_harmonic.dielectric.scf.pw.code = (
+ dielectric_code # we have a specific code for DielectricWorkChain
+ )
builder_harmonic.phonon.phonopy.code = builder_harmonic.phonopy.code
builder_harmonic.phonopy.parameters = Dict(dict=phonon_property.value)
@@ -429,7 +432,9 @@ def get_builder_from_protocol(
"write_mesh": False,
}
)
- builder.phonopy_thermo_dict = Dict(dict=PhononProperty.THERMODYNAMIC.value)
+ builder.phonopy_thermo_dict = Dict(
+ dict=PhononProperty.THERMODYNAMIC.value
+ )
if structure.pbc == (True, False, False):
builder.phonopy_bands_dict = Dict(
@@ -440,11 +445,13 @@ def get_builder_from_protocol(
"band_labels": [GAMMA, "$\\mathrm{X}$"],
}
)
- #change symprec for 1D materials to 1e-3
+ # change symprec for 1D materials to 1e-3
builder.phonopy_pdos_dict["symmetry_tolerance"] = 1e-3
builder.phonopy_thermo_dict["symmetry_tolerance"] = 1e-3
builder.harmonic.symmetry.symprec = orm.Float(1e-3)
- builder.harmonic.phonon.phonopy.parameters = orm.Dict({"symmetry_tolerance": 1e-3})
+ builder.harmonic.phonon.phonopy.parameters = orm.Dict(
+ {"symmetry_tolerance": 1e-3}
+ )
elif structure.pbc == (True, True, False):
symmetry_path = determine_symmetry_path(structure)
@@ -477,15 +484,14 @@ def get_builder_from_protocol(
)
builder.phonopy_thermo_dict = Dict(
- dict= {
- 'tprop': True,
- 'mesh': 200, # 1000 is too heavy
- 'write_mesh': False,
- }
- )
+ dict={
+ "tprop": True,
+ "mesh": 200, # 1000 is too heavy
+ "write_mesh": False,
+ }
+ )
elif simulation_mode == 2:
-
builder_iraman = IRamanSpectraWorkChain.get_builder_from_protocol(
code=phonon_code,
structure=structure,
@@ -494,7 +500,9 @@ def get_builder_from_protocol(
**kwargs,
)
- builder_iraman.dielectric.scf.pw.code = dielectric_code # we have a specific code for DielectricWorkChain
+ builder_iraman.dielectric.scf.pw.code = (
+ dielectric_code # we have a specific code for DielectricWorkChain
+ )
builder_iraman.dielectric.property = dielectric_property
builder_iraman.phonon.phonopy.code = phonopy_code
@@ -510,12 +518,13 @@ def get_builder_from_protocol(
if structure.pbc == (True, False, False):
builder_iraman.symmetry.symprec = orm.Float(1e-3)
- builder_iraman.phonon.phonopy.parameters = orm.Dict({"symmetry_tolerance": 1e-3})
+ builder_iraman.phonon.phonopy.parameters = orm.Dict(
+ {"symmetry_tolerance": 1e-3}
+ )
builder.iraman = builder_iraman
elif simulation_mode == 3:
-
builder_phonon = PhononWorkChain.get_builder_from_protocol(
pw_code=phonon_code,
phonopy_code=phonopy_code,
@@ -558,8 +567,10 @@ def get_builder_from_protocol(
}
)
- builder.phonopy_thermo_dict = Dict(dict=PhononProperty.THERMODYNAMIC.value)
-
+ builder.phonopy_thermo_dict = Dict(
+ dict=PhononProperty.THERMODYNAMIC.value
+ )
+
if structure.pbc == (True, False, False):
builder.phonopy_bands_dict = Dict(
dict={
@@ -569,11 +580,13 @@ def get_builder_from_protocol(
"band_labels": [GAMMA, "$\\mathrm{X}$"],
}
)
- #change symprec for 1D materials to 1e-3
+ # change symprec for 1D materials to 1e-3
builder.phonopy_pdos_dict["symmetry_tolerance"] = 1e-3
builder.phonopy_thermo_dict["symmetry_tolerance"] = 1e-3
builder.phonon.symmetry.symprec = orm.Float(1e-3)
- builder.phonon.phonopy.parameters = orm.Dict({"symmetry_tolerance": 1e-3})
+ builder.phonon.phonopy.parameters = orm.Dict(
+ {"symmetry_tolerance": 1e-3}
+ )
elif structure.pbc == (True, True, False):
symmetry_path = determine_symmetry_path(structure)
@@ -606,15 +619,14 @@ def get_builder_from_protocol(
)
builder.phonopy_thermo_dict = Dict(
- dict= {
- 'tprop': True,
- 'mesh': 200, # 1000 is too heavy
- 'write_mesh': False,
- }
- )
+ dict={
+ "tprop": True,
+ "mesh": 200, # 1000 is too heavy
+ "write_mesh": False,
+ }
+ )
elif simulation_mode == 4:
-
builder_dielectric = DielectricWorkChain.get_builder_from_protocol(
code=dielectric_code,
structure=structure,
@@ -643,9 +655,9 @@ def get_builder_from_protocol(
builder.pop(available_wchains[wchain_idx - 1], None)
builder.phonopy_calc.code = phonopy_code
builder.phonopy_calc.metadata.options.resources = {
- "num_machines": 1,
- "num_mpiprocs_per_machine": 1,
- }
+ "num_machines": 1,
+ "num_mpiprocs_per_machine": 1,
+ }
if structure.pbc == (True, False, False):
builder.phonopy_calc.parameters = orm.Dict({"symmetry_tolerance": 1e-3})
builder.structure = structure
@@ -709,16 +721,22 @@ def run_phonopy(self):
# try in a verdi shell: from plumpy.utils import AttributesFrozendict
if self.ctx.key == "phonon":
# See how this works in PhononWorkChain
- inputs = AttributeDict(self.exposed_inputs(PhonopyCalculation, namespace="phonopy_calc"))
+ inputs = AttributeDict(
+ self.exposed_inputs(PhonopyCalculation, namespace="phonopy_calc")
+ )
inputs.phonopy_data = self.ctx[self.ctx.key].outputs.phonopy_data
inputs.parameters = self.inputs[f"phonopy_{calc_type}_dict"]
-
+
elif self.ctx.key == "harmonic":
# See how this works in HarmonicWorkChain
- inputs = AttributeDict(self.exposed_inputs(PhonopyCalculation, namespace="phonopy_calc"))
- inputs.force_constants = list(self.ctx[self.ctx.key].outputs["vibrational_data"].values())[-1]
+ inputs = AttributeDict(
+ self.exposed_inputs(PhonopyCalculation, namespace="phonopy_calc")
+ )
+ inputs.force_constants = list(
+ self.ctx[self.ctx.key].outputs["vibrational_data"].values()
+ )[-1]
inputs.parameters = self.inputs[f"phonopy_{calc_type}_dict"]
-
+
inputs.metadata.call_link_label = key
future = self.submit(PhonopyCalculation, **inputs)
self.report(
@@ -745,19 +763,19 @@ def results(self):
if self.ctx["bands"].is_finished_ok:
self.out("phonon_bands", self.ctx["bands"].outputs.phonon_bands)
else:
- self.report(f"the child bands PhonopyCalculation failed")
+ self.report("the child bands PhonopyCalculation failed")
failed = True
if self.ctx["pdos"].is_finished_ok:
self.out("phonon_pdos", self.ctx["pdos"].outputs.projected_phonon_dos)
else:
- self.report(f"the child pdos PhonopyCalculation failed")
+ self.report("the child pdos PhonopyCalculation failed")
failed = True
if self.ctx["thermo"].is_finished_ok:
self.out("phonon_thermo", self.ctx["thermo"].outputs.thermal_properties)
else:
- self.report(f"the child thermo PhonopyCalculation failed")
+ self.report("the child thermo PhonopyCalculation failed")
failed = True
if failed:
diff --git a/tests/conftest.py b/tests/conftest.py
index 756bdb9..3f6d75a 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -11,7 +11,8 @@
pytest_plugins = ["aiida.manage.tests.pytest_fixtures"]
-# TODO: import this from the aiidalab-qe app. For now it is copied.
+# TODO: import this from the aiidalab-qe app. For now it is copied.
+
@pytest.fixture
def fixture_localhost(aiida_localhost):
@@ -290,6 +291,7 @@ def projwfc_code(aiida_local_code_factory):
entry_point="quantumespresso.projwfc",
)
+
@pytest.fixture
def phonopy_code(aiida_local_code_factory):
"""Return a `Code` configured for the pw.x executable."""
@@ -298,6 +300,7 @@ def phonopy_code(aiida_local_code_factory):
label="phonopy", executable="bash", entry_point="phonopy.phonopy"
)
+
@pytest.fixture()
def workchain_settings_generator():
"""Return a function that generates a workchain settings dictionary."""
@@ -674,10 +677,14 @@ def _generate_qeapp_workchain(
if magnetization_type == "starting_magnetization"
else tot_magnetization
)
- s2.advanced_settings.magnetization._set_tot_magnetization(
- tot_magnetization
- ) if electronic_type == "insulator" else s2.advanced_settings.magnetization._set_magnetization_values(
- magnetization_values
+ (
+ s2.advanced_settings.magnetization._set_tot_magnetization(
+ tot_magnetization
+ )
+ if electronic_type == "insulator"
+ else s2.advanced_settings.magnetization._set_magnetization_values(
+ magnetization_values
+ )
)
s2.confirm()
diff --git a/tests/test_settings.py b/tests/test_settings.py
index a942e5c..f2ca0f1 100644
--- a/tests/test_settings.py
+++ b/tests/test_settings.py
@@ -1,21 +1,24 @@
import pytest
+
@pytest.mark.usefixtures("sssp")
def test_settings():
"""Test the settings of the vibroscopy app."""
-
+
from aiidalab_qe.app.configuration import ConfigureQeAppWorkChainStep
from ase.build import bulk
from aiida.orm import StructureData
configure_step = ConfigureQeAppWorkChainStep()
# set the input structure
- silicon = bulk('Si', 'diamond', a=5.43)
+ silicon = bulk("Si", "diamond", a=5.43)
structure = StructureData(ase=silicon)
configure_step.input_structure = structure
# select vibrational properties
configure_step.workchain_settings.properties["vibronic"].run.value = True
- assert configure_step.settings["vibronic"].supercell_widget.layout.display == "block"
+ assert (
+ configure_step.settings["vibronic"].supercell_widget.layout.display == "block"
+ )
# test get_panel_value for default starting values
parameters = configure_step.settings["vibronic"].get_panel_value()
print("parameters", parameters)
@@ -32,9 +35,13 @@ def test_settings():
assert configure_step.settings["vibronic"].supercell_widget.layout.display == "none"
# test that we go back to display it when we select the other modes (0 and 2)
configure_step.settings["vibronic"].calc_options.value = 1
- assert configure_step.settings["vibronic"].supercell_widget.layout.display == "block"
+ assert (
+ configure_step.settings["vibronic"].supercell_widget.layout.display == "block"
+ )
configure_step.settings["vibronic"].calc_options.value = 3
- assert configure_step.settings["vibronic"].supercell_widget.layout.display == "block"
+ assert (
+ configure_step.settings["vibronic"].supercell_widget.layout.display == "block"
+ )
# test the reset
configure_step.settings["vibronic"].reset()
parameters = configure_step.settings["vibronic"].get_panel_value()
diff --git a/tests/test_submit.py b/tests/test_submit.py
index 6851a67..a0466a4 100644
--- a/tests/test_submit.py
+++ b/tests/test_submit.py
@@ -1,7 +1,11 @@
import pytest
-from aiidalab_qe.common.widgets import QEAppComputationalResourcesWidget, PwCodeResourceSetupWidget
+from aiidalab_qe.common.widgets import (
+ QEAppComputationalResourcesWidget,
+ PwCodeResourceSetupWidget,
+)
-#@pytest.mark.skip(reason="Skipping this test for now")
+
+# @pytest.mark.skip(reason="Skipping this test for now")
@pytest.mark.usefixtures("sssp")
def test_create_builder_default(
data_regression,
@@ -13,30 +17,30 @@ def test_create_builder_default(
metal, non-magnetic
"""
-
+
app = submit_app_generator(properties=["vibronic"])
-
+
configure_step = app.configure_step
- assert configure_step.settings["vibronic"].calc_options.value == 1
-
+ assert configure_step.settings["vibronic"].calc_options.value == 1
+
submit_step = app.submit_step
- for step in ["phonopy","dielectric"]:
- assert isinstance(submit_step.codes[step],QEAppComputationalResourcesWidget)
- assert isinstance(submit_step.codes["phonon"],PwCodeResourceSetupWidget)
-
+ for step in ["phonopy", "dielectric"]:
+ assert isinstance(submit_step.codes[step], QEAppComputationalResourcesWidget)
+ assert isinstance(submit_step.codes["phonon"], PwCodeResourceSetupWidget)
+
submit_step.codes["phonon"].code_selection.refresh()
submit_step.codes["dielectric"].code_selection.refresh()
submit_step.codes["phonopy"].code_selection.refresh()
-
+
submit_step.codes["pw"].value = pw_code.uuid
submit_step.codes["phonon"].value = pw_code.uuid
submit_step.codes["dielectric"].value = pw_code.uuid
submit_step.codes["phonopy"].value = phonopy_code.uuid
-
+
submit_step.codes["pw"].num_cpus.value = 10
submit_step.codes["phonon"].num_cpus.value = 2
submit_step.codes["dielectric"].num_cpus.value = 3
-
+
submit_step._create_builder()
# since uuid is specific to each run, we remove it from the output
ui_parameters = remove_uuid_fields(submit_step.ui_parameters)
@@ -45,12 +49,23 @@ def test_create_builder_default(
data_regression.check(ui_parameters)
# test if create builder successfully
builder = submit_step._create_builder()
- # In the future, we will check the builder parameters using regresion test
-
+ # In the future, we will check the builder parameters using regresion test
+
# Check that the resources are indeed different for phonon and dielectric workflows.
- assert builder.vibronic.harmonic.phonon.scf.pw.metadata.options.resources['num_mpiprocs_per_machine'] == 2
- assert builder.vibronic.harmonic.dielectric.scf.pw.metadata.options.resources['num_mpiprocs_per_machine'] == 3
-
+ assert (
+ builder.vibronic.harmonic.phonon.scf.pw.metadata.options.resources[
+ "num_mpiprocs_per_machine"
+ ]
+ == 2
+ )
+ assert (
+ builder.vibronic.harmonic.dielectric.scf.pw.metadata.options.resources[
+ "num_mpiprocs_per_machine"
+ ]
+ == 3
+ )
+
+
def remove_uuid_fields(data):
"""
Recursively remove fields that contain UUID values from a dictionary.
@@ -80,4 +95,4 @@ def remove_uuid_fields(data):
return [remove_uuid_fields(item) for item in data]
else:
# Return the value unchanged if it's not a dictionary or list
- return data
\ No newline at end of file
+ return data