First steps
[1]:
import sisl
# We define the root directory where our files are
siesta_files = (
sisl._environ.get_environ_variable("SISL_FILES_TESTS") / "sisl" / "io" / "siesta"
)
info:0: SislInfo: Please install tqdm (pip install tqdm) for better looking progress bars
Your first plots
The most straightforward way to plot things in sisl is to call their plot
method. For example if we have the path to a bands file we can call plot:
[2]:
sisl.get_sile(siesta_files / "SrTiO3.bands").plot()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[2], line 1
----> 1 sisl.get_sile(siesta_files / "SrTiO3.bands").plot()
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:58, in ObjectPlotHandler.__call__(self, *args, **kwargs)
54 if self._default is None:
55 raise TypeError(
56 f"No default plotting function has been defined for {self._obj.__class__.__name__}."
57 )
---> 58 return getattr(self, self._default)(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/_dispatcher.py:68, in AbstractDispatch.__call__(self, *args, **kwargs)
66 def __call__(self, *args, **kwargs):
67 _log.debug(f"call {self.__class__.__name__}{args}", extra={"obj": self})
---> 68 return self.dispatch(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:66, in PlotDispatch.dispatch(self, *args, **kwargs)
64 def dispatch(self, *args, **kwargs):
65 """Runs the plotting function by passing the object instance to it."""
---> 66 return self._plot(self._obj, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:316, in register_data_source.<locals>._plot(obj, __params_info, __signature, *args, **kwargs)
313 if k not in data_kwargs:
314 data_kwargs[k] = v
--> 316 data = data_source_cls.new(obj, *args, **data_kwargs)
318 plot_kwargs = bound.arguments.pop(params_info["plot_var_kwarg"], {})
320 return plot_cls(**{setting_key: data, **bound.arguments, **plot_kwargs})
File ~/.asdf/installs/python/3.12.0/lib/python3.12/functools.py:946, in singledispatchmethod.__get__.<locals>._method(*args, **kwargs)
944 def _method(*args, **kwargs):
945 method = self.dispatcher.dispatch(args[0].__class__)
--> 946 return method.__get__(obj, cls)(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/data/bands.py:325, in BandsData.from_siesta_bands(cls, bands_file)
320 @new.register
321 @classmethod
322 def from_siesta_bands(cls, bands_file: bandsSileSiesta):
323 """Gets the bands data from a SIESTA .bands file"""
--> 325 bands_data = bands_file.read_data(as_dataarray=True)
326 bands_data.k.attrs["axis"] = {
327 "tickvals": bands_data.attrs.pop("ticks"),
328 "ticktext": bands_data.attrs.pop("ticklabels"),
329 }
331 return cls.new(bands_data)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:695, in sile_fh_open.<locals>._wrapper.<locals>.pre_open(self, *args, **kwargs)
693 if hasattr(self, "fh"):
694 return func(self, *args, **kwargs)
--> 695 with self:
696 reset(self)
697 return func(self, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:1076, in Sile.__enter__(self)
1074 def __enter__(self):
1075 """Opens the output file and returns it self"""
-> 1076 self._open()
1077 return self
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:1067, in Sile._open(self)
1065 self.fh = gzip.open(str(self.file), mode=self._mode)
1066 else:
-> 1067 self.fh = self.file.open(self._mode)
1069 # the file should restart the file-read (as per instructed)
1070 self._line = 0
File ~/.asdf/installs/python/3.12.0/lib/python3.12/pathlib.py:1014, in Path.open(self, mode, buffering, encoding, errors, newline)
1012 if "b" not in mode:
1013 encoding = io.text_encoding(encoding)
-> 1014 return io.open(self, mode, buffering, encoding, errors, newline)
FileNotFoundError: [Errno 2] No such file or directory: '_THIS_DIRECTORY_DOES_NOT_EXIST_/sisl/io/siesta/SrTiO3.bands'
You can pass arguments to the plotting function:
[3]:
rho_file = sisl.get_sile(siesta_files / "SrTiO3.RHO")
rho_file.plot(axes="xy", nsc=[2, 1, 1], smooth=True).show("png")
---------------------------------------------------------------------------
SileError Traceback (most recent call last)
Cell In[3], line 2
1 rho_file = sisl.get_sile(siesta_files / "SrTiO3.RHO")
----> 2 rho_file.plot(axes="xy", nsc=[2, 1, 1], smooth=True).show("png")
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:58, in ObjectPlotHandler.__call__(self, *args, **kwargs)
54 if self._default is None:
55 raise TypeError(
56 f"No default plotting function has been defined for {self._obj.__class__.__name__}."
57 )
---> 58 return getattr(self, self._default)(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/_dispatcher.py:68, in AbstractDispatch.__call__(self, *args, **kwargs)
66 def __call__(self, *args, **kwargs):
67 _log.debug(f"call {self.__class__.__name__}{args}", extra={"obj": self})
---> 68 return self.dispatch(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:66, in PlotDispatch.dispatch(self, *args, **kwargs)
64 def dispatch(self, *args, **kwargs):
65 """Runs the plotting function by passing the object instance to it."""
---> 66 return self._plot(self._obj, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:429, in register_sile_method.<locals>._plot(obj, *args, **kwargs)
424 except:
425 raise TypeError(
426 f"Error while parsing arguments to create the call {method}"
427 )
--> 429 data = func(obj, *args, **data_kwargs)
431 plot_kwargs = bound.arguments.pop(params_info["plot_var_kwarg"], {})
433 return plot_cls(**{setting_key: data, **bound.arguments, **plot_kwargs})
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/siesta/binaries.py:2003, in _gridSileSiesta.read_grid(self, index, dtype, *args, **kwargs)
2001 index = kwargs.get("spin", index)
2002 # Read the sizes and cell
-> 2003 nspin, mesh = self.read_grid_size()
2004 lattice = self.read_lattice()
2005 grid = _siesta.read_grid(self.file, nspin, mesh[0], mesh[1], mesh[2])
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/siesta/binaries.py:1983, in _gridSileSiesta.read_grid_size(self)
1981 # Read the sizes
1982 nspin, mesh = _siesta.read_grid_sizes(self.file)
-> 1983 self._fortran_check("read_grid_size", "could not read grid sizes.")
1984 return nspin, mesh
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/siesta/sile.py:82, in SileBinSiesta._fortran_check(self, method, message, ret_msg)
80 msg = f"{self!s}.{method} {message} (ierr={ierr})"
81 if not ret_msg:
---> 82 raise SileError(msg)
83 if ret_msg:
84 return msg
SileError: rhoSileSiesta(SrTiO3.RHO, base=_THIS_DIRECTORY_DOES_NOT_EXIST_/sisl/io/siesta).read_grid_size could not read grid sizes. (ierr=2)
Some objects can be plotted in different ways, and just calling plot
will do it in the default way. You can however choose which plot you want from the available representations. For example, out of a PDOS file you can plot the PDOS (the default):
[4]:
pdos_file = sisl.get_sile(siesta_files / "SrTiO3.PDOS")
pdos_file.plot(groups=[{"species": "O", "name": "O"}, {"species": "Ti", "name": "Ti"}])
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[4], line 3
1 pdos_file = sisl.get_sile(siesta_files / "SrTiO3.PDOS")
----> 3 pdos_file.plot(groups=[{"species": "O", "name": "O"}, {"species": "Ti", "name": "Ti"}])
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:58, in ObjectPlotHandler.__call__(self, *args, **kwargs)
54 if self._default is None:
55 raise TypeError(
56 f"No default plotting function has been defined for {self._obj.__class__.__name__}."
57 )
---> 58 return getattr(self, self._default)(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/_dispatcher.py:68, in AbstractDispatch.__call__(self, *args, **kwargs)
66 def __call__(self, *args, **kwargs):
67 _log.debug(f"call {self.__class__.__name__}{args}", extra={"obj": self})
---> 68 return self.dispatch(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:66, in PlotDispatch.dispatch(self, *args, **kwargs)
64 def dispatch(self, *args, **kwargs):
65 """Runs the plotting function by passing the object instance to it."""
---> 66 return self._plot(self._obj, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:316, in register_data_source.<locals>._plot(obj, __params_info, __signature, *args, **kwargs)
313 if k not in data_kwargs:
314 data_kwargs[k] = v
--> 316 data = data_source_cls.new(obj, *args, **data_kwargs)
318 plot_kwargs = bound.arguments.pop(params_info["plot_var_kwarg"], {})
320 return plot_cls(**{setting_key: data, **bound.arguments, **plot_kwargs})
File ~/.asdf/installs/python/3.12.0/lib/python3.12/functools.py:946, in singledispatchmethod.__get__.<locals>._method(*args, **kwargs)
944 def _method(*args, **kwargs):
945 method = self.dispatcher.dispatch(args[0].__class__)
--> 946 return method.__get__(obj, cls)(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/data/pdos.py:277, in PDOSData.from_siesta_pdos(cls, pdos_file)
275 """Gets the PDOS from a SIESTA PDOS file"""
276 # Get the info from the .PDOS file
--> 277 geometry, E, PDOS = pdos_file.read_data()
279 return cls.new(PDOS, geometry, E)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:678, in sile_fh_open.<locals>._wrapper.<locals>.pre_open(self, *args, **kwargs)
675 def _reset(self):
676 pass
--> 678 with self:
679 # REMARK this requires the __enter__ to seek(0)
680 # for the file, and currently it does
681 _reset(self)
682 return func(self, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:1076, in Sile.__enter__(self)
1074 def __enter__(self):
1075 """Opens the output file and returns it self"""
-> 1076 self._open()
1077 return self
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:1067, in Sile._open(self)
1065 self.fh = gzip.open(str(self.file), mode=self._mode)
1066 else:
-> 1067 self.fh = self.file.open(self._mode)
1069 # the file should restart the file-read (as per instructed)
1070 self._line = 0
File ~/.asdf/installs/python/3.12.0/lib/python3.12/pathlib.py:1014, in Path.open(self, mode, buffering, encoding, errors, newline)
1012 if "b" not in mode:
1013 encoding = io.text_encoding(encoding)
-> 1014 return io.open(self, mode, buffering, encoding, errors, newline)
FileNotFoundError: [Errno 2] No such file or directory: '_THIS_DIRECTORY_DOES_NOT_EXIST_/sisl/io/siesta/SrTiO3.PDOS'
or the geometry (not the default, you need to specify it):
[5]:
pdos_file.plot.geometry(atoms_scale=0.7)
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[5], line 1
----> 1 pdos_file.plot.geometry(atoms_scale=0.7)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/_dispatcher.py:68, in AbstractDispatch.__call__(self, *args, **kwargs)
66 def __call__(self, *args, **kwargs):
67 _log.debug(f"call {self.__class__.__name__}{args}", extra={"obj": self})
---> 68 return self.dispatch(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:66, in PlotDispatch.dispatch(self, *args, **kwargs)
64 def dispatch(self, *args, **kwargs):
65 """Runs the plotting function by passing the object instance to it."""
---> 66 return self._plot(self._obj, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:429, in register_sile_method.<locals>._plot(obj, *args, **kwargs)
424 except:
425 raise TypeError(
426 f"Error while parsing arguments to create the call {method}"
427 )
--> 429 data = func(obj, *args, **data_kwargs)
431 plot_kwargs = bound.arguments.pop(params_info["plot_var_kwarg"], {})
433 return plot_cls(**{setting_key: data, **bound.arguments, **plot_kwargs})
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/siesta/pdos.py:43, in pdosSileSiesta.read_geometry(self)
41 def read_geometry(self) -> Geometry:
42 """Read the geometry with coordinates and correct orbital counts"""
---> 43 return self.read_data()[0]
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:678, in sile_fh_open.<locals>._wrapper.<locals>.pre_open(self, *args, **kwargs)
675 def _reset(self):
676 pass
--> 678 with self:
679 # REMARK this requires the __enter__ to seek(0)
680 # for the file, and currently it does
681 _reset(self)
682 return func(self, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:1076, in Sile.__enter__(self)
1074 def __enter__(self):
1075 """Opens the output file and returns it self"""
-> 1076 self._open()
1077 return self
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:1067, in Sile._open(self)
1065 self.fh = gzip.open(str(self.file), mode=self._mode)
1066 else:
-> 1067 self.fh = self.file.open(self._mode)
1069 # the file should restart the file-read (as per instructed)
1070 self._line = 0
File ~/.asdf/installs/python/3.12.0/lib/python3.12/pathlib.py:1014, in Path.open(self, mode, buffering, encoding, errors, newline)
1012 if "b" not in mode:
1013 encoding = io.text_encoding(encoding)
-> 1014 return io.open(self, mode, buffering, encoding, errors, newline)
FileNotFoundError: [Errno 2] No such file or directory: '_THIS_DIRECTORY_DOES_NOT_EXIST_/sisl/io/siesta/SrTiO3.PDOS'
Updating your plots
When you call .plot()
, you receive a Plot
object:
[6]:
pdos_plot = pdos_file.plot()
type(pdos_plot)
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[6], line 1
----> 1 pdos_plot = pdos_file.plot()
2 type(pdos_plot)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:58, in ObjectPlotHandler.__call__(self, *args, **kwargs)
54 if self._default is None:
55 raise TypeError(
56 f"No default plotting function has been defined for {self._obj.__class__.__name__}."
57 )
---> 58 return getattr(self, self._default)(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/_dispatcher.py:68, in AbstractDispatch.__call__(self, *args, **kwargs)
66 def __call__(self, *args, **kwargs):
67 _log.debug(f"call {self.__class__.__name__}{args}", extra={"obj": self})
---> 68 return self.dispatch(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:66, in PlotDispatch.dispatch(self, *args, **kwargs)
64 def dispatch(self, *args, **kwargs):
65 """Runs the plotting function by passing the object instance to it."""
---> 66 return self._plot(self._obj, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/_plotables.py:316, in register_data_source.<locals>._plot(obj, __params_info, __signature, *args, **kwargs)
313 if k not in data_kwargs:
314 data_kwargs[k] = v
--> 316 data = data_source_cls.new(obj, *args, **data_kwargs)
318 plot_kwargs = bound.arguments.pop(params_info["plot_var_kwarg"], {})
320 return plot_cls(**{setting_key: data, **bound.arguments, **plot_kwargs})
File ~/.asdf/installs/python/3.12.0/lib/python3.12/functools.py:946, in singledispatchmethod.__get__.<locals>._method(*args, **kwargs)
944 def _method(*args, **kwargs):
945 method = self.dispatcher.dispatch(args[0].__class__)
--> 946 return method.__get__(obj, cls)(*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/viz/data/pdos.py:277, in PDOSData.from_siesta_pdos(cls, pdos_file)
275 """Gets the PDOS from a SIESTA PDOS file"""
276 # Get the info from the .PDOS file
--> 277 geometry, E, PDOS = pdos_file.read_data()
279 return cls.new(PDOS, geometry, E)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:678, in sile_fh_open.<locals>._wrapper.<locals>.pre_open(self, *args, **kwargs)
675 def _reset(self):
676 pass
--> 678 with self:
679 # REMARK this requires the __enter__ to seek(0)
680 # for the file, and currently it does
681 _reset(self)
682 return func(self, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:1076, in Sile.__enter__(self)
1074 def __enter__(self):
1075 """Opens the output file and returns it self"""
-> 1076 self._open()
1077 return self
File ~/checkouts/readthedocs.org/user_builds/sisl/envs/latest/lib/python3.12/site-packages/sisl/io/sile.py:1067, in Sile._open(self)
1065 self.fh = gzip.open(str(self.file), mode=self._mode)
1066 else:
-> 1067 self.fh = self.file.open(self._mode)
1069 # the file should restart the file-read (as per instructed)
1070 self._line = 0
File ~/.asdf/installs/python/3.12.0/lib/python3.12/pathlib.py:1014, in Path.open(self, mode, buffering, encoding, errors, newline)
1012 if "b" not in mode:
1013 encoding = io.text_encoding(encoding)
-> 1014 return io.open(self, mode, buffering, encoding, errors, newline)
FileNotFoundError: [Errno 2] No such file or directory: '_THIS_DIRECTORY_DOES_NOT_EXIST_/sisl/io/siesta/SrTiO3.PDOS'
Plot
objects are a kind of Workflow
. You can check the sisl.nodes
documentation to understand what exactly this means. But long story short, this means that the computation is split in multiple nodes, as you can see in the following diagram:
[7]:
pdos_plot.network.visualize(notebook=True)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[7], line 1
----> 1 pdos_plot.network.visualize(notebook=True)
NameError: name 'pdos_plot' is not defined
With that knowledge, when you update the inputs of a plot, only the necessary parts are recalculated. In that way, you may avoid repeating expensive calculations or reading to files that no longer exist. Inputs are updated with update_inputs
:
[8]:
pdos_plot.update_inputs(Erange=[-3, 3])
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[8], line 1
----> 1 pdos_plot.update_inputs(Erange=[-3, 3])
NameError: name 'pdos_plot' is not defined
Some inputs are a bit cumbersome to write by hand, and therefore along your journey you’ll find that plots have some helper methods to modify inputs much faster. For example, PdosPlot
has the split_DOS
method, which generates groups of orbitals for you.
[9]:
pdos_plot.split_DOS()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[9], line 1
----> 1 pdos_plot.split_DOS()
NameError: name 'pdos_plot' is not defined
Don’t worry!
Each plot class has its own dedicated notebook in the documentation to guide you through all the knobs that they have!
Different plotting backends
Hidden between all the inputs, you can find a very special input: backend
.
This input allows you to choose the plotting backend used to display a plot. If you don’t like the default one, just change it!
[10]:
pdos_plot.update_inputs(backend="matplotlib")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[10], line 1
----> 1 pdos_plot.update_inputs(backend="matplotlib")
NameError: name 'pdos_plot' is not defined
Let’s go back to the default one, plotly
.
[11]:
pdos_plot.update_inputs(backend="plotly")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[11], line 1
----> 1 pdos_plot.update_inputs(backend="plotly")
NameError: name 'pdos_plot' is not defined
Further customization
If you are a master of some backend, you’ll be happy to know that you can run any backend specific method on the plot. For example, plotly has a method called add_vline
that draws a vertical line:
[12]:
pdos_plot.add_vline(-1).add_vline(2)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[12], line 1
----> 1 pdos_plot.add_vline(-1).add_vline(2)
NameError: name 'pdos_plot' is not defined
In fact, if you need the raw figure for something, you can find it under the figure
attribute.
[13]:
type(pdos_plot.figure)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[13], line 1
----> 1 type(pdos_plot.figure)
NameError: name 'pdos_plot' is not defined
Discover more
This notebook has shown you the most basic features of the framework with the hope that you will be hooked into it :)
If it succeeded, we invite you to check the rest of the documentation. It only gets better from here!