Download IPython notebook here. Binder badge.

GitHub issues by-label

WavefunctionPlot

The WavefunctionPlot class will help you very easily generate and display wavefunctions from a Hamiltonian or any other source. If you already have your wavefunction in a grid, you can use GridPlot.

Note

WavefunctionPlot is just an extension of GridPlot, so everything in the GridPlot notebook applies and this notebook will only display the additional features.

[1]:
import sisl
import sisl.viz

Generating wavefunctions from a hamiltonian

We will create a toy graphene tight binding hamiltonian, but you could have read the Hamiltonian from any source. Note that your hamiltonian needs to contain the corresponding geometry with the right orbitals, otherwise we have no idea what’s the shape of the wavefunction.

[2]:
import numpy as np

r = np.linspace(0, 3.5, 50)
f = np.exp(-r)

orb = sisl.AtomicOrbital('2pzZ', (r, f))
geom = sisl.geom.graphene(orthogonal=True, atoms=sisl.Atom(6, orb))
geom = geom.move([0, 0, 5])
H = sisl.Hamiltonian(geom)
H.construct([(0.1, 1.44), (0, -2.7)], )

Now that we have our hamiltonian, plotting a wavefunction is as simple as:

[3]:
H.plot.wavefunction()
info:0: SislInfo: The plot has been initialized correctly, but the current settings were not enough to generate the figure.
Error: GridPlot._get_representation() takes 2 positional arguments but 3 were given
'<sisl.viz.plots.grid.WavefunctionPlot object at 0x7f4e69cdee60>'

That truly is an ugly wavefunction.

Selecting the wavefunction

By default, WavefunctionPlot gives you the first wavefunction at the gamma point. You can control this behavior by tuning the i and k settings.

For example, to get the second wavefunction at the gamma point:

[4]:
plot = H.plot.wavefunction(i=2, k=(0, 0, 0))
plot
info:0: SislInfo: The plot has been initialized correctly, but the current settings were not enough to generate the figure.
Error: GridPlot._get_representation() takes 2 positional arguments but 3 were given
'<sisl.viz.plots.grid.WavefunctionPlot object at 0x7f4e69cdfee0>'

You can also select the spin with the spin setting (if you have, of course, a spin polarized Hamiltonian).

Note

If you update the number of the wavefunction, the eigenstates are already calculated, so there’s no need to recalculate them. However, changing the k point or the spin component will trigger a recalculation of the eigenstates.

Grid precision

The wavefunction is projected in a grid, and how fine that grid is will determine the resolution. You can control this with the grid_prec setting, which accepts the grid precision in Angstrom. Let’s check the difference in 2D, where it will be best appreciated:

[5]:
plot.update_settings(axes="xy", k=(0,0,0), transforms=["square"]) # by default grid_prec is 0.2 Ang
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [5], in <module>
----> 1 plot.update_settings(axes="xy", k=(0,0,0), transforms=["square"])

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:437, in ConfigurableMeta.__new__.<locals>.update_settings(self, *args, **kwargs)
    436 def update_settings(self, *args, **kwargs):
--> 437     return self._update_settings(*args, **kwargs)

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

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

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plotutils.py:829, in repeat_if_children.<locals>.apply_to_all_plots(obj, children_sel, *args, **kwargs)
    825     obj.get_figure()
    827 else:
--> 829     return method(obj, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:888, in vizplotly_settings.<locals>.decorator.<locals>.func(obj, *args, **kwargs)
    885 @wraps(method)
    886 def func(obj, *args, **kwargs):
    887     getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 888     return method(obj, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plot.py:1112, in Plot.set_data(self, update_fig, **kwargs)
   1104 @repeat_if_children
   1105 @vizplotly_settings('before')
   1106 def set_data(self, update_fig = True, **kwargs):
   1107     """ Method to process the data that has been read beforehand by read_data() and prepare the figure
   1108
   1109     If everything is succesful, it calls the next step in plotting (`get_figure`)
   1110     """
-> 1112     self._for_backend = self._set_data()
   1114     if update_fig:
   1115         self.get_figure()

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plots/grid.py:1583, in WavefunctionPlot._set_data(self, i, geometry, grid, k, grid_prec, nsc)
   1577 # Finally, insert the wavefunction values into the grid.
   1578 sisl.physics.electron.wavefunction(
   1579     wf_state.state, grid, geometry=tiled_geometry,
   1580     k=k, spinor=0, spin=spin
   1581 )
-> 1583 return super()._set_data(nsc=nsc, trace_name=f"WF {i} ({wf_state.eig[0]:.2f} eV)")

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plots/grid.py:536, in GridPlot._set_data(self, axes, nsc, interp, trace_name, transforms, represent, grid_file, x_range, y_range, z_range, plot_geom, geom_kwargs, transform_bc, reduce_method)
    533 self.offsets["origin"] = grid.origin
    535 # Choose the representation of the grid that we want to display
--> 536 grid.grid = self._get_representation(grid, represent)
    538 # We will tile the grid now, as at the moment there's no good way to tile it afterwards
    539 # Note that this means extra computation, as we are transforming (skewed_2d) or calculating
    540 # the isosurfaces (3d) using more than one unit cell (FIND SMARTER WAYS!)
    541 for ax, reps in enumerate(nsc):

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

TypeError: GridPlot._get_representation() takes 2 positional arguments but 3 were given
[6]:
plot.update_settings(grid_prec=0.05)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [6], in <module>
----> 1 plot.update_settings(grid_prec=0.05)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:437, in ConfigurableMeta.__new__.<locals>.update_settings(self, *args, **kwargs)
    436 def update_settings(self, *args, **kwargs):
--> 437     return self._update_settings(*args, **kwargs)

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

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

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plotutils.py:829, in repeat_if_children.<locals>.apply_to_all_plots(obj, children_sel, *args, **kwargs)
    825     obj.get_figure()
    827 else:
--> 829     return method(obj, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:888, in vizplotly_settings.<locals>.decorator.<locals>.func(obj, *args, **kwargs)
    885 @wraps(method)
    886 def func(obj, *args, **kwargs):
    887     getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 888     return method(obj, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plot.py:1112, in Plot.set_data(self, update_fig, **kwargs)
   1104 @repeat_if_children
   1105 @vizplotly_settings('before')
   1106 def set_data(self, update_fig = True, **kwargs):
   1107     """ Method to process the data that has been read beforehand by read_data() and prepare the figure
   1108
   1109     If everything is succesful, it calls the next step in plotting (`get_figure`)
   1110     """
-> 1112     self._for_backend = self._set_data()
   1114     if update_fig:
   1115         self.get_figure()

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plots/grid.py:1583, in WavefunctionPlot._set_data(self, i, geometry, grid, k, grid_prec, nsc)
   1577 # Finally, insert the wavefunction values into the grid.
   1578 sisl.physics.electron.wavefunction(
   1579     wf_state.state, grid, geometry=tiled_geometry,
   1580     k=k, spinor=0, spin=spin
   1581 )
-> 1583 return super()._set_data(nsc=nsc, trace_name=f"WF {i} ({wf_state.eig[0]:.2f} eV)")

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plots/grid.py:536, in GridPlot._set_data(self, axes, nsc, interp, trace_name, transforms, represent, grid_file, x_range, y_range, z_range, plot_geom, geom_kwargs, transform_bc, reduce_method)
    533 self.offsets["origin"] = grid.origin
    535 # Choose the representation of the grid that we want to display
--> 536 grid.grid = self._get_representation(grid, represent)
    538 # We will tile the grid now, as at the moment there's no good way to tile it afterwards
    539 # Note that this means extra computation, as we are transforming (skewed_2d) or calculating
    540 # the isosurfaces (3d) using more than one unit cell (FIND SMARTER WAYS!)
    541 for ax, reps in enumerate(nsc):

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

TypeError: GridPlot._get_representation() takes 2 positional arguments but 3 were given

Much better, isn’t it? Notice how it didn’t look that bad in 3d, because the grid is smooth, so it’s values are nicely interpolated. You can also appreciate this by setting zsmooth to "best" in 2D, which does an “OK job” at guessing the values.

[7]:
plot.update_settings(grid_prec=0.2, zsmooth="best")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [7], in <module>
----> 1 plot.update_settings(grid_prec=0.2, zsmooth="best")

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:437, in ConfigurableMeta.__new__.<locals>.update_settings(self, *args, **kwargs)
    436 def update_settings(self, *args, **kwargs):
--> 437     return self._update_settings(*args, **kwargs)

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

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

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plotutils.py:829, in repeat_if_children.<locals>.apply_to_all_plots(obj, children_sel, *args, **kwargs)
    825     obj.get_figure()
    827 else:
--> 829     return method(obj, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:888, in vizplotly_settings.<locals>.decorator.<locals>.func(obj, *args, **kwargs)
    885 @wraps(method)
    886 def func(obj, *args, **kwargs):
    887     getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 888     return method(obj, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plot.py:1112, in Plot.set_data(self, update_fig, **kwargs)
   1104 @repeat_if_children
   1105 @vizplotly_settings('before')
   1106 def set_data(self, update_fig = True, **kwargs):
   1107     """ Method to process the data that has been read beforehand by read_data() and prepare the figure
   1108
   1109     If everything is succesful, it calls the next step in plotting (`get_figure`)
   1110     """
-> 1112     self._for_backend = self._set_data()
   1114     if update_fig:
   1115         self.get_figure()

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plots/grid.py:1583, in WavefunctionPlot._set_data(self, i, geometry, grid, k, grid_prec, nsc)
   1577 # Finally, insert the wavefunction values into the grid.
   1578 sisl.physics.electron.wavefunction(
   1579     wf_state.state, grid, geometry=tiled_geometry,
   1580     k=k, spinor=0, spin=spin
   1581 )
-> 1583 return super()._set_data(nsc=nsc, trace_name=f"WF {i} ({wf_state.eig[0]:.2f} eV)")

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plots/grid.py:536, in GridPlot._set_data(self, axes, nsc, interp, trace_name, transforms, represent, grid_file, x_range, y_range, z_range, plot_geom, geom_kwargs, transform_bc, reduce_method)
    533 self.offsets["origin"] = grid.origin
    535 # Choose the representation of the grid that we want to display
--> 536 grid.grid = self._get_representation(grid, represent)
    538 # We will tile the grid now, as at the moment there's no good way to tile it afterwards
    539 # Note that this means extra computation, as we are transforming (skewed_2d) or calculating
    540 # the isosurfaces (3d) using more than one unit cell (FIND SMARTER WAYS!)
    541 for ax, reps in enumerate(nsc):

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

TypeError: GridPlot._get_representation() takes 2 positional arguments but 3 were given

Warning

Keep in mind that a finer grid will occupy more memory and take more time to generate and render, and sometimes it might be unnecessary to make your grid very fine, specially if it’s smooth.

GridPlot settings

As stated at the beggining of this notebook, you have all the power of GridPlot available to you. Therefore you can, for example, display supercells of the resulting wavefunctions (please don’t tile the hamiltonian! :)).

[8]:
plot.update_settings(axes="xyz", nsc=[2,2,1], grid_prec=0.1, transforms=[],
    isos=[
        {"val": -0.07, "opacity": 1, "color": "salmon"},
        {"val": 0.07, "opacity": 0.7, "color": "blue"}
    ],
    geom_kwargs={"atoms_style": dict(color=["orange", "red", "green", "pink"])},
)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [8], in <module>
----> 1 plot.update_settings(axes="xyz", nsc=[2,2,1], grid_prec=0.1, transforms=[],
      2     isos=[
      3         {"val": -0.07, "opacity": 1, "color": "salmon"},
      4         {"val": 0.07, "opacity": 0.7, "color": "blue"}
      5     ],
      6     geom_kwargs={"atoms_style": dict(color=["orange", "red", "green", "pink"])},
      7 )

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:437, in ConfigurableMeta.__new__.<locals>.update_settings(self, *args, **kwargs)
    436 def update_settings(self, *args, **kwargs):
--> 437     return self._update_settings(*args, **kwargs)

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

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

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plotutils.py:829, in repeat_if_children.<locals>.apply_to_all_plots(obj, children_sel, *args, **kwargs)
    825     obj.get_figure()
    827 else:
--> 829     return method(obj, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:888, in vizplotly_settings.<locals>.decorator.<locals>.func(obj, *args, **kwargs)
    885 @wraps(method)
    886 def func(obj, *args, **kwargs):
    887     getattr(obj, method_name)(**kwargs, **extra_kwargs)
--> 888     return method(obj, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plot.py:1112, in Plot.set_data(self, update_fig, **kwargs)
   1104 @repeat_if_children
   1105 @vizplotly_settings('before')
   1106 def set_data(self, update_fig = True, **kwargs):
   1107     """ Method to process the data that has been read beforehand by read_data() and prepare the figure
   1108
   1109     If everything is succesful, it calls the next step in plotting (`get_figure`)
   1110     """
-> 1112     self._for_backend = self._set_data()
   1114     if update_fig:
   1115         self.get_figure()

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plots/grid.py:1583, in WavefunctionPlot._set_data(self, i, geometry, grid, k, grid_prec, nsc)
   1577 # Finally, insert the wavefunction values into the grid.
   1578 sisl.physics.electron.wavefunction(
   1579     wf_state.state, grid, geometry=tiled_geometry,
   1580     k=k, spinor=0, spin=spin
   1581 )
-> 1583 return super()._set_data(nsc=nsc, trace_name=f"WF {i} ({wf_state.eig[0]:.2f} eV)")

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/plots/grid.py:536, in GridPlot._set_data(self, axes, nsc, interp, trace_name, transforms, represent, grid_file, x_range, y_range, z_range, plot_geom, geom_kwargs, transform_bc, reduce_method)
    533 self.offsets["origin"] = grid.origin
    535 # Choose the representation of the grid that we want to display
--> 536 grid.grid = self._get_representation(grid, represent)
    538 # We will tile the grid now, as at the moment there's no good way to tile it afterwards
    539 # Note that this means extra computation, as we are transforming (skewed_2d) or calculating
    540 # the isosurfaces (3d) using more than one unit cell (FIND SMARTER WAYS!)
    541 for ax, reps in enumerate(nsc):

File ~/checkouts/readthedocs.org/user_builds/sisl/checkouts/v0.12.0/sisl/viz/configurable.py:969, in _populate_with_settings.<locals>.f_default_setting_args(self, *args, **kwargs)
    966         except KeyError:
    967             pass
--> 969 return f(self, *args, **kwargs)

TypeError: GridPlot._get_representation() takes 2 positional arguments but 3 were given

We hope you enjoyed what you learned!


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

[9]:
thumbnail_plot = plot

if thumbnail_plot:
    thumbnail_plot.show("png")
warn:0: SislWarning: There is no plotting backend selected, so the plot can't be displayed.