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

New BandsPdosWidget #581

Merged
merged 2 commits into from
Feb 5, 2024
Merged

New BandsPdosWidget #581

merged 2 commits into from
Feb 5, 2024

Conversation

AndresOrtegaGuerrero
Copy link
Member

This PR introduces a new bands_pdos_widget using plotly, the widget include options of drag, pan and toogle , save a snapshot , and download the data.

The formating of the bands/pdos has been moved from the result plugin to the common/bandspdoswidget.py

It allows different selection of atoms to consider, or different representations ( We can modified or create new according to your suggestions)

For spin polarized calculations it represents bands_up in red, and bands_down in blue. For non polarized the line is in black color.

The new _projections_curated_options allows to curated SOC pdos.

The legend has a wheel fixing #552

Copy link

codecov bot commented Dec 13, 2023

Codecov Report

Attention: 64 lines in your changes are missing coverage. Please review.

Comparison is base (c990a59) 77.55% compared to head (678fc46) 80.63%.

❗ Current head 678fc46 differs from pull request most recent head de6723d. Consider uploading reports for the commit de6723d to get more accurate results

Files Patch % Lines
src/aiidalab_qe/common/bandpdoswidget.py 81.14% 56 Missing ⚠️
...aiidalab_qe/plugins/electronic_structure/result.py 63.63% 4 Missing ⚠️
src/aiidalab_qe/plugins/bands/result.py 66.66% 2 Missing ⚠️
src/aiidalab_qe/plugins/pdos/result.py 71.42% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #581      +/-   ##
==========================================
+ Coverage   77.55%   80.63%   +3.08%     
==========================================
  Files          54       50       -4     
  Lines        3831     3609     -222     
==========================================
- Hits         2971     2910      -61     
+ Misses        860      699     -161     
Flag Coverage Δ
python-3.10 80.63% <82.12%> (+3.08%) ⬆️
python-3.8 80.67% <82.12%> (+3.08%) ⬆️
python-3.9 80.67% <82.12%> (+3.08%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@AndresOrtegaGuerrero
Copy link
Member Author

AndresOrtegaGuerrero commented Dec 13, 2023

Please have a look , test it let me know any further changes and/or developments @unkcpz @superstar54 .

@AndresOrtegaGuerrero
Copy link
Member Author

I think in a second PR, i can add different test for the new widget

@unkcpz unkcpz added this to the v2024.4.0 milestone Dec 15, 2023
@unkcpz unkcpz mentioned this pull request Dec 15, 2023
@unkcpz
Copy link
Member

unkcpz commented Jan 10, 2024

Pinning @mikibonacci, he mentioned he has a use case that needs some adaption on the bandsplotwidget which will be replaced by this PR, so he can give a quick review and a test.

I didn't start looking at the code, but give it a try on the qeapp, from the outcome it is exactly what we needed, thanks for the great work @AndresOrtegaGuerrero.

@AndresOrtegaGuerrero
Copy link
Member Author

Pinning @mikibonacci, he mentioned he has a use case that needs some adaption on the bandsplotwidget which will be replaced by this PR, so he can give a quick review and a test.

I didn't start looking at the code, but give it a try on the qeapp, from the outcome it is exactly what we needed, thanks for the great work @AndresOrtegaGuerrero.

Thank you! , please let me know we can gather ideas of what is missing ,or a different approach , or for the future,

Copy link
Member

@unkcpz unkcpz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AndresOrtegaGuerrero I give it a first go.

I notice that the data validation is missing. The BandPdosWidget accept AiiDA node as input which make the widget not generic and vulnerable to the future change of BandData.
In the original bandsplotwidget, we add a middle layer of dict type between AiiDA node and input for the widget. The object pass to the widget then can be validated by the schema.
I'd suggest adding this design back to the new widget. For the data validation, you can try to use pydantic.

Besides, the unit tests for the newly added widget would be very useful.

src/aiidalab_qe/plugins/bands/result.py Outdated Show resolved Hide resolved
tests/test_plugins_electronic_structure.py Outdated Show resolved Hide resolved
tests/test_plugins_pdos.py Show resolved Hide resolved
@AndresOrtegaGuerrero
Copy link
Member Author

AndresOrtegaGuerrero commented Jan 11, 2024

@AndresOrtegaGuerrero I give it a first go.

I notice that the data validation is missing. The BandPdosWidget accept AiiDA node as input which make the widget not generic and vulnerable to the future change of BandData. In the original bandsplotwidget, we add a middle layer of dict type between AiiDA node and input for the widget. The object pass to the widget then can be validated by the schema. I'd suggest adding this design back to the new widget. For the data validation, you can try to use pydantic.

Besides, the unit tests for the newly added widget would be very useful.

@unkcpz Thank you , you mean that the widget doesnt call get_pdos_data , exports_bands_data (these have the form of the original implementation getting a dictionary) from the widget using the node, but instead that the output from these functions is the input for the widget right ? In the widget I use _get_bands_data , _get_pdos_data .

Copy link
Member

@unkcpz unkcpz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes @AndresOrtegaGuerrero. I have some request upon method names and especially the flow of data/objects.

This is a widget for dealing with the bands/pdos data, convert the data to the format that plotly can plot a plot object. Then generate the plotly plot object and render it to the ipyoutput.

I'd suggest at least separate methods for plotly plot object creating to a class BandPdosPlot. The class getting a formatted bands/pdos data and knowing how to create a plotly plot object. Then for the BandPdosWidget, it dealing with 1) parsing the data to the formatted data and pass to BandPdosPlot 2) dealing the logic with the QeApp, such as initialize the widget and hide the widget.

src/aiidalab_qe/common/bandpdoswidget.py Outdated Show resolved Hide resolved
Comment on lines 22 to 40
- description: HTML description of the widget.
- dos_atoms_group: Dropdown widget to select the grouping of atoms for PDOS plotting.
- dos_plot_group: Dropdown widget to select the type of PDOS contributions to plot.
- selected_atoms: Text widget to select specific atoms for PDOS plotting.
- wrong_syntax: HTML widget to display an error message for incorrect atom selection syntax.
- update_plot_button: Button widget to update the plot.
- download_button: Button widget to download the data.
- export_dir: Path to the directory for exporting data.
- dos_data: PDOS data.
- fermi_energy: Fermi energy value.
- bands_data: Band structure data.
- band_labels: Labels and values for band structure plotting.
- bands_xaxis: X-axis settings for band structure plot.
- bands_yaxis: Y-axis settings for band structure plot.
- dos_xaxis: X-axis settings for PDOS plot.
- dos_yaxis: Y-axis settings for PDOS plot.
- bandsplot_widget: Plotly widget for band structure and PDOS plot.
- bands_widget: Output widget to display the bandsplot widget.
- pdos_options_out: Output widget to clear specific widgets.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think most of these attributes don't need to be exposed.

src/aiidalab_qe/common/bandpdoswidget.py Outdated Show resolved Hide resolved
src/aiidalab_qe/common/bandpdoswidget.py Outdated Show resolved Hide resolved

def _band_xaxis(self):
"""Function to return the xaxis for the bands plot."""
import plotly.graph_objects as go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to put the import for each function? If not, please move it to the top.

src/aiidalab_qe/common/bandpdoswidget.py Outdated Show resolved Hide resolved
Comment on lines 241 to 243
if my_clean_labels:
if i not in my_clean_labels:
if my_clean_labels[-1][-1] == i[1]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if my_clean_labels:
if i not in my_clean_labels:
if my_clean_labels[-1][-1] == i[1]:
if my_clean_labels and (i not in my_clean_labels) and (my_clean_labels[-1][-1] == i[1]):

I guess this is the same? If not can you try to simplify it, too many layers of nest indicate things that can be polished.

# Output widget to clear the specific widgets
self.pdos_options_out = ipw.Output()

def download_data(_=None):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this function out?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When i do it , it doesnt work i will check if i can move it out

Comment on lines 107 to 111
# Information for the plot
self.dos_data = self._get_dos_data()
self.fermi_energy = self._get_fermi_energy()
self.bands_data = self._get_bands_data()
self.band_labels = self._bands_labeling(self.bands_data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see the reason why these attributes need to initialize here. When the widget initialized, there is no plot, so these attributes are not needed.


return dosyaxis

def _bandsplot_widget(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name is bandsplot but it also deal with pdos, better to be called as bandpdosplot.
Moreover, this function return a plotly plot objcet, so I'd call it get_bandpdos_plot.

The data flow is more clean to be like: data -> plotly plot object -> ipyoutput widget, can you check the PR and try to apply this flow?

@unkcpz
Copy link
Member

unkcpz commented Feb 5, 2024

Hi @AndresOrtegaGuerrero, it is all in good shape. Before merge, I want to ask for a final test on using the new widget for the phonon bands plot. Can you or @mikibonacci give a test on using the new widget for it? I think it is a good proof that the API exposed by the new widget is generic enough for most of use cases.

@unkcpz
Copy link
Member

unkcpz commented Feb 5, 2024

Since this replace the widget_bandsplot, it should be able to remove the dependency from setup.cfg.

The old bandsplot widget https://github.com/aiidalab/widget-bandsplot was separately
maintained in the repo with complex and not well modulized JS code.
In this PR, the new bandspdoswidget is introduced to have it all implemented in python
and in ipywidget framework with using plotly as plot engine.
The output band structure is in a publish ready level with a flexible control on the
groups of orbitals/atoms user want to projected.
@unkcpz unkcpz merged commit 87ba4dc into main Feb 5, 2024
16 checks passed
@unkcpz unkcpz deleted the new_bandswidget branch February 5, 2024 13:53
@unkcpz unkcpz mentioned this pull request Feb 29, 2024
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants