Download IPython notebook here. Binder badge.

GitHub issues by-label

BandsPlot

[1]:
import sisl
import sisl.viz.plotly
# This is just for convenience to retreive files
siesta_files = sisl._environ.get_environ_variable("SISL_FILES_TESTS") / "sisl" / "io" / "siesta"

Let’s get a bands_plot from a .bands file

[2]:
bands_plot = sisl.get_sile( siesta_files / "SrTiO3.bands").plot()
info:0: SislInfo:

The plot has been initialized correctly, but the current settings were not enough to generate the figure.
Error: Could not read or generate data for BandsPlot from any of the possible sources.
Here are the errors for each source:
        - aiida bands: AttributeError.'NoneType' object has no attribute '_get_bandplot_data'
        - path: ValueError.You need to provide at least 2 points of the path to draw the bands. Please update the 'path' setting. The current path is: []
        - band structure: ValueError.No band structure (k points path) was provided
        - bands file: FileNotFoundError.[Errno 2] No such file or directory: '_THIS_DIRECTORY_DOES_NOT_EXIST_/sisl/io/siesta/SrTiO3.bands'

and see what we’ve got:

[3]:
bands_plot

Getting the bands that you want

By default, BandsPlot gives you the 15 bands below and above 0 eV (which is interpreted as the fermi level).

There are two main ways to specify the bands that you want to display: Erange and bands_range.

As you may have guessed, Erange specifies the energy range that is displayed:

[4]:
bands_plot.update_settings(Erange=[-10, 10])
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/3335527519.py in <module>
----> 1 bands_plot.update_settings(Erange=[-10, 10])

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

while with bands_range you can actually indicate the indices.

However, note that ``Erange`` has preference over ``bands_range``, therefore you need to set Erange to None if you want the change to take effect.

[5]:
bands_plot.update_settings(bands_range=[6, 15], Erange=None)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/3881200607.py in <module>
----> 1 bands_plot.update_settings(bands_range=[6, 15], Erange=None)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

If your fermi level is not correctly set or you want a different energy reference, you can provide a value for E0 to specify where your 0 should be and the bands to display will be automatically calculated from that.

However, if you want to update E0 after the plot has been build and you want BandsPlot to recalculate the bands for you you will need to set Erange and bands_range to None again.

[6]:
bands_plot.update_settings(E0=-10, bands_range=None, Erange=None)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/360385505.py in <module>
----> 1 bands_plot.update_settings(E0=-10, bands_range=None, Erange=None)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Notice how only 25 bands are displayed now: the only 10 that are below 0 eV (there are no lower states) and 15 above 0 eV.

[7]:
# Set them back to "normal"
bands_plot = bands_plot.update_settings(E0=0, bands_range=None, Erange=None)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/2942253412.py in <module>
      1 # Set them back to "normal"
----> 2 bands_plot = bands_plot.update_settings(E0=0, bands_range=None, Erange=None)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Notice that in spin polarized bands, you can select the spins to display using the ``spin`` setting, just pass a list of spin components (e.g. spin=[0]).

Quick styling

If all you want is to change the color and width of the bands, there’s one simple solution: use the bands_color and bands_width settings.

Let’s show them in red:

[8]:
bands_plot.update_settings(bands_color="red")
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/2159710323.py in <module>
----> 1 bands_plot.update_settings(bands_color="red")

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

And now in green but also make them wider:

[9]:
bands_plot.update_settings(bands_color="green", bands_width=3)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/2533980131.py in <module>
----> 1 bands_plot.update_settings(bands_color="green", bands_width=3)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

If you have spin polarized bands, bands_color will modify the color of the first spin channel, while the second one can be tuned with spindown_color.

[10]:
bands_plot = bands_plot.update_settings(bands_color="black", bands_width=1)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/2189703166.py in <module>
----> 1 bands_plot = bands_plot.update_settings(bands_color="black", bands_width=1)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Displaying the smallest gaps

The easiest thing to do is to let BandsPlot discover where the (minimum) gaps are.

This is indicated by setting the gap parameter to True. One can also use gap_color if a particular color is desired.

[11]:
bands_plot.update_settings(gap=True, gap_color="green", Erange=[-10,10]) # We reduce Erange just to see it better
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/865024897.py in <module>
----> 1 bands_plot.update_settings(gap=True, gap_color="green", Erange=[-10,10]) # We reduce Erange just to see it better

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

This displays the minimum gaps. However there may be some issues with it: it will show all gaps with the minimum value. That is, if you have repeated points in the brillouin zone it will display multiple gaps that are equivalent.

What’s worse, if the region where your gap is is very flat, two consecutive points might have the same energy. Multiple gaps will be displayed one glued to another.

To help cope with this issues, you have the direct_gaps_only and gap_tol.

In this case, since we have no direct gaps, setting direct_gaps_only will hide them all:

[12]:
bands_plot.update_settings(direct_gaps_only=True)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/828232860.py in <module>
----> 1 bands_plot.update_settings(direct_gaps_only=True)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

The example for gap_tol is not that good, but it is illustrative of what gap_tol does. It is the minimum k-distance between two points to consider them irrelevant to show different gaps.

In this case, if we set gap_tol all the way up to 3, the plot will consider the two gamma points to be part of the same “point” and therefore it will only show the gap once.

[13]:
bands_plot.update_settings(direct_gaps_only=False, gap_tol=3)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/3334029801.py in <module>
----> 1 bands_plot.update_settings(direct_gaps_only=False, gap_tol=3)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

This is not what gap_tol is meant for, since it is thought to remediate the effect of locally flat bands, but still you can get the idea of what it does.

[14]:
bands_plot = bands_plot.update_settings(gap=False, gap_tol=0.01)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/1113209297.py in <module>
----> 1 bands_plot = bands_plot.update_settings(gap=False, gap_tol=0.01)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Displaying custom gaps

If you are not happy with the gaps that the plot is displaying for you or you simply want gaps that are not the smallest ones, you can always use custom_gaps.

Custom gaps should be a list where each item specifies how to draw that given gap. See the setting’s help message:

[15]:
print(bands_plot.get_param("custom_gaps").help)
List of all the gaps that you want to display.

 Each item is a dict. Structure of the expected dicts:{
        'from': K value where to start measuring the gap.
                    It can be either the label of the k-point or the numeric value in the plot.
        'to': K value where to end measuring the gap.
                    It can be either the label of the k-point or the numeric value in the plot.
        'color': The color with which the gap should be displayed
        'spin': The spin components where the gap should be calculated.
}

So, for example, if we want to plot the gamma-gamma gap:

[16]:
bands_plot.update_settings(custom_gaps=[{"from": "Gamma", "to": "Gamma", "color": "red"}])
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/305599999.py in <module>
----> 1 bands_plot.update_settings(custom_gaps=[{"from": "Gamma", "to": "Gamma", "color": "red"}])

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Notice how we got the gap probably not where we wanted, since it would be better to have it in the middle Gamma point, which is more visible. As the help message of custom_gaps states, you can also pass the K value instead of a label.

Now, you’ll be happy to know that you can easily access the k values of all labels, as they are stored as attributes in the bands dataarray, which you can find in bands_plot.bands:

[17]:
bands_plot.bands.attrs
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/2915369081.py in <module>
----> 1 bands_plot.bands.attrs

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Now all we need to do is to grab the value for the second gamma point:

[18]:
gap_k = None
for val, label in zip(bands_plot.bands.attrs["ticks"], bands_plot.bands.attrs["ticklabels"]):
    if label == "Gamma":
        gap_k = val
gap_k
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/2887685888.py in <module>
      1 gap_k = None
----> 2 for val, label in zip(bands_plot.bands.attrs["ticks"], bands_plot.bands.attrs["ticklabels"]):
      3     if label == "Gamma":
      4         gap_k = val
      5 gap_k

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

And use it to build a custom gap:

[19]:
bands_plot.update_settings(custom_gaps=[{"from": gap_k, "to": gap_k, "color": "orange"}])
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/515739783.py in <module>
----> 1 bands_plot.update_settings(custom_gaps=[{"from": gap_k, "to": gap_k, "color": "orange"}])

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Individual band styling

The bands_color and bands_width should be enough for most uses. However, you may want to style each band differently. Since we can not support every possible case, you can pass a function to the add_band_trace_data. Here’s the help message:

[20]:
print(bands_plot.get_param("add_band_trace_data").help)
A function that receives each band (as a DataArray) and adds data to the trace. It also recieves the plot object.
            The returned data may even overwrite the existing one, therefore it can be useful to fully customize your bands plot (individual style for each band if you want).

You can build a dummy function to print the band and see how it looks like. Notice that you only get those bands that are inside the range specified for the plot, therefore the first band here is band 11!

[21]:
def add_trace_data(band, self):
    """Dummy function to see the band DataArray"""
    if band.band == 11:
        print(band)

    return {}

bands_plot.update_settings(add_band_trace_data=add_trace_data)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/3671765896.py in <module>
      6     return {}
      7
----> 8 bands_plot.update_settings(add_band_trace_data=add_trace_data)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Just as an educational example, we are going to style the bands according to this conditions: - If the band is +- 5 eV within the fermi level, we are going to draw markers whose size is proportional to the gradient of the band at each point. - Otherwise, we will just display the bands as purple dotted lines that fade as we get far from the fermi level (just because we can!)

Note: Of course, to modify traces, one must have some notion of how plotly traces work. Just hit plotly’s visual reference page https://plotly.com/python/ for inspiration.

[22]:
import numpy as np
def draw_gradient(band, self):
    """
    Takes a band and styles it according to its energy dispersion.

    NOTE: If it's to far from the fermi level, it fades it in purple for additional coolness.
    """
    dist_from_Ef = np.max(abs(band))
    if dist_from_Ef < 5:
        return {
            "mode": "lines+markers",
            "marker_size": np.abs(np.gradient(band))*40,
        }
    else:
        return {
            "line_color": "purple",
            "line_dash": "dot",
            "opacity": 1-float(dist_from_Ef/10)
        }

bands_plot.update_settings(add_band_trace_data=draw_gradient)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_3746/3591778590.py in <module>
     19         }
     20
---> 21 bands_plot.update_settings(add_band_trace_data=draw_gradient)

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in update_settings(self, *args, **kwargs)
    419             # the available kwargs for the plot class and provide more help to the user
    420             def update_settings(self, *args, **kwargs):
--> 421                 return self._update_settings(*args, **kwargs)
    422
    423             update_settings.__doc__ = f"Updates the settings of this plot.\n\nDocs for {new_cls.__name__}:\n\n{get_configurable_docstring(new_cls)}"

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _update_settings(self, run_updates, **kwargs)
    554             #Do things after updating the settings
    555             if len(self.settings_history.last_updated) > 0 and run_updates:
--> 556                 self._run_updates(self.settings_history.last_updated)
    557
    558         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in _run_updates(self, for_keys)
    582         # Execute the functions that we need to execute.
    583         for f_name in func_names:
--> 584             getattr(self, f_name)()
    585
    586         return self

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plotutils.py in apply_to_all_plots(obj, childs_sel, *args, **kwargs)
    817         else:
    818
--> 819             return method(obj, *args, **kwargs)
    820
    821     return apply_to_all_plots

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in func(obj, *args, **kwargs)
    881             def func(obj, *args, **kwargs):
    882                 getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 883                 return method(obj, *args, **kwargs)
    884
    885         elif when == 'after':

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in set_data(self, update_fig, **kwargs)
   1126         self._starting_traces = len(self.data)
   1127
-> 1128         self._set_data()
   1129
   1130         if update_fig:

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/configurable.py in f_default_setting_args(self, *args, **kwargs)
    962                     pass
    963
--> 964         return f(self, *args, **kwargs)
    965
    966     return f_default_setting_args

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plots/bands.py in _set_data(self, Erange, E0, bands_range, spin, bands_width, bands_color, spindown_color, add_band_trace_data, draw_before_bands)
    565
    566         # Shift all the bands to the reference
--> 567         filtered_bands = self.bands - E0
    568
    569         # Get the bands that matter for the plot

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in __getattr__(self, key)
    734                 pass
    735
--> 736         raise AttributeError(f"The attribute '{key}' was not found either in the plot, its figure, or in shared attributes.")
    737
    738     def __setattr__(self, key, val):

AttributeError: The attribute 'bands' was not found either in the plot, its figure, or in shared attributes.

Displaying spin texture

If your bands plot comes from a non-colinear spin calculation (or is using a Hamiltonian with non-colinear spin), you can pass "x", "y" or "z" to the spin setting in order to get a display of the spin texture.

More docs in this section will come soon, just ask for them if you need to use it and it doesn’t quite work for you!

We hope you enjoyed what you learned!


This next cell is just to create the thumbnail for the notebook in the docs

[23]:
thumbnail_plot = bands_plot

if thumbnail_plot:
    thumbnail_plot.show("png")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_3746/1796618154.py in <module>
      2
      3 if thumbnail_plot:
----> 4     thumbnail_plot.show("png")

~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.11.0/sisl/viz/plotly/plot.py in show(self, listen, return_figWidget, *args, **kwargs)
   1187                 warn(e)
   1188
-> 1189         return self.figure.show(*args, **kwargs)
   1190
   1191     def _ipython_display_(self, return_figWidget=False, **kwargs):

~/checkouts/readthedocs.org/user_builds/sisl/conda/v0.11.0/lib/python3.8/site-packages/plotly/basedatatypes.py in show(self, *args, **kwargs)
   3396         import plotly.io as pio
   3397
-> 3398         return pio.show(self, *args, **kwargs)
   3399
   3400     def to_json(self, *args, **kwargs):

~/checkouts/readthedocs.org/user_builds/sisl/conda/v0.11.0/lib/python3.8/site-packages/plotly/io/_renderers.py in show(fig, renderer, validate, **kwargs)
    387
    388     # Mimetype renderers
--> 389     bundle = renderers._build_mime_bundle(fig_dict, renderers_string=renderer, **kwargs)
    390     if bundle:
    391         if not ipython_display:

~/checkouts/readthedocs.org/user_builds/sisl/conda/v0.11.0/lib/python3.8/site-packages/plotly/io/_renderers.py in _build_mime_bundle(self, fig_dict, renderers_string, **kwargs)
    295                         setattr(renderer, k, v)
    296
--> 297                 bundle.update(renderer.to_mimebundle(fig_dict))
    298
    299         return bundle

~/checkouts/readthedocs.org/user_builds/sisl/conda/v0.11.0/lib/python3.8/site-packages/plotly/io/_base_renderers.py in to_mimebundle(self, fig_dict)
    126
    127     def to_mimebundle(self, fig_dict):
--> 128         image_bytes = to_image(
    129             fig_dict,
    130             format=self.format,

~/checkouts/readthedocs.org/user_builds/sisl/conda/v0.11.0/lib/python3.8/site-packages/plotly/io/_kaleido.py in to_image(fig, format, width, height, scale, validate, engine)
    132     # Raise informative error message if Kaleido is not installed
    133     if scope is None:
--> 134         raise ValueError(
    135             """
    136 Image export using the "kaleido" engine requires the kaleido package,

ValueError:
Image export using the "kaleido" engine requires the kaleido package,
which can be installed using pip:
    $ pip install -U kaleido