Tutorial 2: Open a Multiview of Panels

This tutorial shows how to display multiple panels simultaneously using scivianna’s layout system.

Introduction to Layouts

Scivianna provides two layout classes for displaying multiple panels:

Layout

Description

SplitLayout

Two panels split vertically or horizontally with a draggable divider

GridStackLayout

Multiple panels in a grid with drag-and-drop rearrangement

Step 1: SplitLayout - Two Panels Side by Side

SplitLayout divides the screen into two areas. You can split vertically (side by side) or horizontally (top and bottom).

from pathlib import Path
from scivianna.slave import ComputeSlave
from scivianna.interface.med_interface import MEDInterface
from scivianna.panel.panel_2d import Panel2D
from scivianna.layout.split import SplitLayout, SplitItem, SplitDirection
from scivianna.constants import GEOMETRY
import scivianna.input_file

# Path to a built-in example MED file
med_file_path = Path(scivianna.input_file.__file__).parent / "power.med"

Vertical Split (Side by Side)

Creates two panels displayed left and right with a vertical divider.

# Create two ComputeSlaves
slave1 = ComputeSlave(MEDInterface)
slave2 = ComputeSlave(MEDInterface)

# Load the same file in both slaves (or different files)
slave1.read_file(med_file_path, GEOMETRY)
slave2.read_file(med_file_path, GEOMETRY)

# Create two Panel2D instances
panel_left = Panel2D(slave=slave1, name="Left Panel")
panel_right = Panel2D(slave=slave2, name="Right Panel")

# Create a SplitItem defining the layout
split_item = SplitItem(
    panel_1=panel_left,
    panel_2=panel_right,
    direction=SplitDirection.VERTICAL,  # Side by side
)

# Create the SplitLayout
split_layout = SplitLayout(split_item)

# Display
# split_layout

Horizontal Split (Top and Bottom)

Creates two panels displayed one above the other with a horizontal divider.

# Create the split item with horizontal direction
split_item_h = SplitItem(
    panel_1=panel_left,
    panel_2=panel_right,
    direction=SplitDirection.HORIZONTAL,  # Top and bottom
)

# Create the SplitLayout
split_layout_h = SplitLayout(split_item_h)

# Display
# split_layout_h

SplitLayout Features

  • Draggable divider: Click and drag the divider to resize panels

  • Panel switching: Click on panel icons in the sidebar to switch between panels

  • Duplication: Use the duplicate button to split a panel further (creating nested splits)

  • Save/Restore: Layouts can be saved to and restored from zip files

Step 2: Nested Splits - Multiple Panels

SplitItem can be nested to create more complex layouts with multiple panels.

# Create three slaves and panels
slave_a = ComputeSlave(MEDInterface)
slave_b = ComputeSlave(MEDInterface)
slave_c = ComputeSlave(MEDInterface)

slave_a.read_file(med_file_path, GEOMETRY)
slave_b.read_file(med_file_path, GEOMETRY)
slave_c.read_file(med_file_path, GEOMETRY)

panel_a = Panel2D(slave=slave_a, name="Panel A")
panel_b = Panel2D(slave=slave_b, name="Panel B")
panel_c = Panel2D(slave=slave_c, name="Panel C")

# Create nested split item:
#       +----------+----------+
#       |          |          |
#       |  Panel A |  Panel B |
#       |          |          |
#       +----------+----------+
#       |                     |
#       |       Panel C       │
#       |                     |
#       +----------+----------+

inner_split = SplitItem(
    panel_1=panel_a,
    panel_2=panel_b,
    direction=SplitDirection.VERTICAL,  # A | B
)

# Actually for 3 panels we need a different approach:
# Left: Panel A (top/bottom split with Panel C)
# Right: Panel B

nested_split = SplitItem(
    panel_1=inner_split,
    panel_2=panel_c,
    direction=SplitDirection.HORIZONTAL,  # A over C
)

nested_layout = SplitLayout(nested_split)
# nested_layout/

Step 3: GridStackLayout - Multiple Panels in a Grid

GridStackLayout provides a more flexible grid-based layout with drag-and-drop rearrangement.

from scivianna.layout.gridstack import GridStackLayout

# Create four slaves and panels
slaves = [
    ComputeSlave(MEDInterface) for _ in range(4)
]
panels = {}

for i, slave in enumerate(slaves):
    slave.read_file(med_file_path, GEOMETRY)
    panels[f"Grid Panel {i}"] = Panel2D(slave=slave, name=f"Grid Panel {i}")

# Defining the panels bounds:

#       +----------+----------+
#       |          |          |
#       |    0     |    1     |
#       |          |          |
#       +----------+----------+
#       |          |          |
#       |    2     |    3     |
#       |          |          |
#       +----------+----------+
bounds_x = {
    "Grid Panel 0": [0, 4],
    "Grid Panel 1": [5, 9],
    "Grid Panel 2": [0, 4],
    "Grid Panel 3": [5, 9]
}
bounds_y = {
    "Grid Panel 0": [0, 4],
    "Grid Panel 1": [0, 4],
    "Grid Panel 2": [5, 9],
    "Grid Panel 3": [5, 9]
}

# Create a GridStackLayout with the panels
grid_layout = GridStackLayout(
    visualisation_panels = panels,
    bounds_x = bounds_x,
    bounds_y = bounds_y
)

# Display
# grid_layout

GridStackLayout Features

  • Drag-and-drop: Drag panel borders to resize cells

  • Resizable grid: Right-click on a cell to adjust rows/columns

  • Panel switching: Click on panel icons in the sidebar to switch between panels

  • Save/Restore: Layouts can be saved to and restored from zip files

Step 4: Save and Restore Layouts

Layouts can be saved to zip files and restored later.

# Save the layout to a zip file
# split_layout.save_to_zip("my_layout.zip", include_files=True)

# Restore the layout from a zip file
# restored_layout = SplitLayout.restore_from_zip(
#     "my_layout.zip",
#     include_files=True,
# )

Step 5: Synchronized Fields

Multiple panels can synchronize their displayed field when the sync_field argument is set at True.

# Create two panels sharing the same slave
shared_slave = ComputeSlave(MEDInterface)
shared_slave.read_file(med_file_path, GEOMETRY)

panel_sync1 = Panel2D(slave=shared_slave, name="Sync Panel 1")
panel_sync2 = Panel2D(slave=shared_slave, name="Sync Panel 2")

panel_sync1.sync_field = True
panel_sync2.sync_field = True

# When you change the field in one panel, both update
sync_split = SplitItem(
    panel_1=panel_sync1,
    panel_2=panel_sync2,
    direction=SplitDirection.VERTICAL,
)

sync_layout = SplitLayout(sync_split)
# sync_layout

Summary

In this tutorial, you learned:

  1. SplitLayout: Two-panel layouts with draggable dividers — vertical (side by side) and horizontal (stacked)

  2. Nested splits: Building complex multi-panel layouts by nesting SplitItem instances

  3. GridStackLayout: Flexible multi-panel grids with drag-and-drop resizing and configurable cell bounds

  4. Save/Restore: Persisting layout configurations to zip files with save_to_zip() and restore_from_zip()

  5. Field synchronization: Linking field selections across panels using sync_field=True

Next Steps