# Load the default AiiDA profile.
from aiida import load_profile, orm

load_profile();

AiiDA Viewers#

This module contains the viewers, which are used to visualize AiiDA objects.

How to visualize an AiiDA object#

The simplest way is to import the viewer() function and call it with the object:

from aiidalab_widgets_base import viewer

p = orm.Dict(
    dict={
        "parameter 1": "some string",
        "parameter 2": 2,
        "parameter 3": 3.0,
        "parameter 4": [1, 2, 3],
    }
)
vwr = viewer(p.store(), downloadable=True)
display(vwr)

The function takes two inputs: the object to show and an optional flag for displaying the download button. The function gives back a viewer object for notebook display. If the viewer for the object is not available, the object itself is returned, allowing for a very basic representation of it.

An alternative way is to use the AiidaNodeViewWidget class:

from aiida import orm

from aiidalab_widgets_base import AiidaNodeViewWidget

p = orm.Dict(
    dict={
        "parameter 1": "some string",
        "parameter 2": 2,
        "parameter 3": 3.0,
        "parameter 4": [1, 2, 3],
    }
)
wdgt = AiidaNodeViewWidget(node=p.store())
display(wdgt)

Using the AiidaNodeViewWidget lets you visualize different AiiDA objects without making a new widget. Just update the node attribute of the widget as in the example below:

from aiida import plugins
from ase.build import molecule

m = molecule("H2O")
m.center(vacuum=2.0)

StructureData = plugins.DataFactory("core.structure")
s = StructureData(ase=m)

wdgt.node = s.store()

When you update the node attribute, the widget will automatically refresh and display the new object, such as a water molecule in this case.

Build-in viewers#

The viewers for several AiiDA objects are available:

  • DictViewer for the orm.Dict object representation.

  • StructureDataViewer for the orm.StructureData and orm.CifData object representation.

  • FolderDataViewer for the orm.FolderDataViewer object representation.

  • ProcessNodeViewerWidget for the orm.ProcessNode (and its children such as orm.CalcJobNode or orm.WorkChainNode) object representation.

  • and others…

To see the full list of available viewers, visit the module API documentation.

List of build-in viewers#

In this section, we list the build-in viewers and show how to use them.

Dict viewer#

The DictViewer is used to visualize dictionaries.

from aiida import plugins

from aiidalab_widgets_base.viewers import DictViewer

Dict = plugins.DataFactory("core.dict")
p = Dict(
    dict={
        "Parameter": "super long string " * 4,
        "parameter 2": "value 2",
        "parameter 3": 1,
        "parameter 4": 2,
    }
)
vwr = DictViewer(p.store(), downloadable=True)
display(vwr)

CifData and StructureData viewer#

The StructureDataViewer is used to visualize both CifData`` and StructureData`` objects.

from ase.build import bulk, molecule

from aiidalab_widgets_base.viewers import StructureDataViewer

# create bulk Pt
pt = bulk("Pt", cubic=True)

# Cif data.
CifData = plugins.DataFactory("core.cif")
s = CifData(ase=pt)
vwr_cif = StructureDataViewer(s.store())
display(vwr_cif)

# Structure data.
m = molecule("H2O")
m.center(vacuum=2.0)

StructureData = plugins.DataFactory("core.structure")
s = StructureData(ase=m)
vwr_structure = StructureDataViewer(s.store())
display(vwr_structure)

FolderData viewer#

The FolderDataViewer is used to visualize FolderData objects.

import io

from aiida import plugins

FolderData = plugins.DataFactory("core.folder")
fd = FolderData()
with io.StringIO("content of test1 file") as fobj:
    fd.put_object_from_filelike(fobj, path="test1.txt")
with io.StringIO("content of test2 file") as fobj:
    fd.put_object_from_filelike(fobj, path="test2.txt")
with io.StringIO("content of test_long file" * 1000) as fobj:
    fd.put_object_from_filelike(fobj, path="test_long.txt")
vwr = viewer(fd.store(), downloadable=True)
display(vwr)

ProcessNode viewer#

The ProcessNodeViewerWidget is used to visualize CalcFunctionNode and WorkFunctionNode objects.

from aiida import engine, orm
from aiida.workflows.arithmetic.add_multiply import add, add_multiply

from aiidalab_widgets_base.viewers import ProcessNodeViewerWidget

result, workfunction = engine.run_get_node(
    add_multiply, {"x": orm.Int(3), "y": orm.Int(4), "z": orm.Int(5)}
)
vwr_workfunction = ProcessNodeViewerWidget(workfunction)
display(vwr_workfunction)

result, calcfunction = engine.run_get_node(add, {"x": orm.Int(3), "y": orm.Int(4)})
vwr_calcfunction = ProcessNodeViewerWidget(calcfunction)
display(vwr_calcfunction)

Create a custom viewer#

To create a custom viewer one usually inherits from an existing ipywidgets widget and implements the logic for displaying the object. The only requirement is that the first argument of the constructor is the object to visualize.

Also to make the new class recognizable by the viewer() function, the class should be decorated with the register_viewer_widget() decorator.

To demonstrate how this works we create a simple viewer for the orm.Int object:

import ipywidgets as ipw

from aiidalab_widgets_base import register_viewer_widget


@register_viewer_widget("data.core.int.Int.")
class IntViewerWidget(ipw.HTML):
    def __init__(self, node, **kwargs):
        super().__init__(**kwargs)
        self.value = f"Int object: <b>{node.value}<b>"


vwr = viewer(orm.Int(3).store())
display(vwr)

The string to be put as an argument of the register_viewer_widget decorator can be obtained from the node_type property of an object.

i_node = orm.Int(1)
print(i_node.node_type)