Miscellaneous Tutorial
This tutorial shows some miscellaneous views in figpack extensions.
figpack_force_graph
The figpack_force_graph extension provides visualizations of graphs using the force-graph library.
Installation
After installing figpack, run:
figpack extensions install --upgrade figpack_force_graph
Basic Usage
Here’s a simple example showing how to create a force-directed graph:
from figpack_force_graph import ForceGraphView
import numpy as np
def create_graph():
"""Create a graph using the dynamic add methods"""
graph = ForceGraphView(background_color="#000000", highlight_connected=True)
# Add nodes dynamically
graph.add_node("central", name="Central Hub", val=20, color="#e74c3c")
# Add satellite nodes
colors = ["#3498db", "#2ecc71", "#f39c12", "#9b59b6", "#1abc9c"]
for i in range(5):
node_id = f"satellite_{i}"
graph.add_node(
node_id,
name=f"Satellite {i+1}",
val=np.random.randint(8, 15),
color=colors[i],
)
graph.add_link("central", node_id, color="#95a5a6", width=2)
# Add some interconnections
graph.add_link("satellite_0", "satellite_2", color="#bdc3c7", width=1)
graph.add_link("satellite_1", "satellite_3", color="#bdc3c7", width=1)
graph.add_link("satellite_2", "satellite_4", color="#bdc3c7", width=1)
return graph
# Create and display the graph
graph = create_graph()
graph.show(title="Force Graph Example", open_in_browser=True)
Node Properties
Each node in the graph can have the following properties:
id
(required): Unique identifier for the nodename
(optional): Display name shown in tooltipsval
(optional): Numeric value affecting node sizecolor
(optional): Color of the node (CSS color string)
Link Properties
Each link in the graph can have the following properties:
source
(required): ID of the source nodetarget
(required): ID of the target nodecolor
(optional): Color of the link (CSS color string)width
(optional): Width of the link line
View Configuration
The ForceGraphView accepts several configuration options:
background_color
: Background color of the graph canvashighlight_connected
: Whether to highlight connected nodes on hovercooldown_ticks
: Number of simulation ticks before stoppingenable_node_click
: Enable/disable node click interactionsenable_node_hover
: Enable/disable node hover interactions
For more advanced usage and additional configuration options, please refer to the extension documentation.
figpack_3d
The figpack_3d extension provides interactive 3D visualizations using the Three.js library.
Installation
After installing figpack, run:
figpack extensions install --upgrade figpack_3d
Basic Usage
Here’s a simple example showing how to create a 3D scene:
from figpack_3d import ThreeDView
import numpy as np
def create_3d_scene():
"""Create a basic 3D scene with geometric objects"""
view = ThreeDView(background_color="#222222")
# Add a red cube at the center
view.add_cube(position=(0, 0, 0), color="#ff4444")
# Add blue spheres around the cube
for i in range(4):
angle = i * np.pi / 2
x = 3 * np.cos(angle)
z = 3 * np.sin(angle)
view.add_sphere(position=(x, 0, z), color="#4444ff")
# Add a wireframe cylinder
view.add_cylinder(
position=(0, 2, 0),
color="#44ff44",
wireframe=True
)
return view
# Create and display the 3D scene
scene = create_3d_scene()
scene.show(title="3D Scene Example", open_in_browser=True)
The figpack_3d extension supports cubes, spheres, and cylinders with customizable positions, colors, rotations, and scales. Mouse controls allow rotation (drag) and zooming (mouse wheel).
For more advanced usage, please refer to the extension documentation.
Mesh View
See the example in extension_packages/figpack_3d/examples/sphere_mesh_example.py.
Click the various tabs in the following:
figpack_experimental
Some other miscellaneous views are provided in the figpack_experimental extension, including editable notes and lossy video display.
Installation
After installing figpack, run:
figpack extensions install --upgrade figpack_experimental
Lossy Video View
Here’s a simple example showing how to create and display a lossy video:
import figpack_experimental.views as fpj
import numpy as np
def create_circle(frame, center, radius, color):
h, w = frame.shape[:2]
y, x = np.ogrid[:h, :w]
dist = np.sqrt((x - center[0])**2 + (y - center[1])**2)
mask = dist <= radius
frame[mask] = color
np.random.seed(0)
width = 640
height = 480
num_frames = 300
fps = 30.0
# Create black background frames
data = np.zeros((num_frames, height, width, 3), dtype=np.uint8)
# Initialize 3 balls with random positions and velocities
balls = []
colors = [(255,0,0), (0,255,0), (0,0,255)] # RGB colors
radius = 20
for i in range(3):
balls.append({
'pos': np.array([
np.random.randint(radius, width-radius),
np.random.randint(radius, height-radius)
], dtype=float),
'vel': np.array([
np.random.uniform(-30, 30),
np.random.uniform(-30, 30)
]),
'color': colors[i]
})
# Animate balls
for frame_idx in range(num_frames):
frame = data[frame_idx]
# Update each ball
for ball in balls:
# Update position
ball['pos'] += ball['vel']
# Bounce off walls
if ball['pos'][0] <= radius or ball['pos'][0] >= width-radius:
ball['vel'][0] *= -1
if ball['pos'][1] <= radius or ball['pos'][1] >= height-radius:
ball['vel'][1] *= -1
# Keep ball in bounds
ball['pos'][0] = np.clip(ball['pos'][0], radius, width-radius)
ball['pos'][1] = np.clip(ball['pos'][1], radius, height-radius)
# Draw ball
create_circle(frame, ball['pos'], radius, ball['color'])
# Create and show video
v = fpj.LossyVideo(data=data, fps=fps)
v.show(title="Bouncing Balls Animation", open_in_browser=True)
fMRI BOLD View
The figpack_experimental extension includes a view for visualizing fMRI BOLD data from NIfTI files.
import figpack_experimental.views as jv
url = "https://s3.amazonaws.com/openneuro.org/ds006661/sub-001/func/sub-001_task-main_run-01_bold.nii.gz"
v = jv.FmriBold.from_nii(url)
v.show(title="fMRI BOLD Example", open_in_browser=True)
fMRI Video Example
Here’s an example showing how to create a lossy video from an fMRI dataset:
import os
import urllib.request
import numpy as np
import nibabel as nib
import figpack_experimental.views as jv
url = "https://s3.amazonaws.com/openneuro.org/ds006661/sub-001/func/sub-001_task-main_run-01_bold.nii.gz"
local_fname = "tmp-sub-001_task-main_run-01_bold.nii.gz"
# download if needed
if not os.path.exists(local_fname):
print(f"Downloading from {url}...")
urllib.request.urlretrieve(url, local_fname)
print("Download complete.")
else:
print(f"{local_fname} already exists. Skipping download.")
img = nib.load(local_fname)
data = img.get_fdata()
# scale to 0-255, and bring 99th percentile to 255
pct_99 = np.percentile(data, 99)
data = np.clip(data, 0, pct_99)
data = ((data / pct_99) * 255).astype(np.uint8)
# extract a slice
slice = data[:, :, -1]
# slice is W x H x T
# permute this so that it is T x H x W
slice = np.transpose(slice, (2, 1, 0))
# reverse the H direction so that it is not upside down
slice = slice[:, ::-1, :]
# make rgb channels, grayscale
slice_rgb = np.repeat(slice[:, :, :, np.newaxis], 3, axis=3)
# make a LossyVideo
v = jv.LossyVideo(slice_rgb, fps=10)
v.show(title="fMRI Series", open_in_browser=True)
MountainLayout
The MountainLayout provides a workspace-style interface with a left panel for view buttons and controls, and a right panel with dual tab workspaces (north and south). This layout is ideal for applications that need to manage multiple views in a workspace environment.
Basic Usage
Here’s a simple example showing how to create a MountainLayout:
import numpy as np
import figpack.views as vv
def create_mountain_layout():
"""Create a mountain layout with multiple views and a control panel"""
# Create some sample views
ts_graph = vv.TimeseriesGraph(y_label="Signal")
t = np.linspace(0, 10, 1000)
y = np.sin(2 * np.pi * t)
ts_graph.add_line_series(name="sine wave", t=t, y=y, color="blue")
# Create an image view
image_data = np.random.rand(100, 100, 3)
image_uint8 = (image_data * 255).astype(np.uint8)
from PIL import Image
import io
pil_image = Image.fromarray(image_uint8)
png_buffer = io.BytesIO()
pil_image.save(png_buffer, format='PNG')
png_bytes = png_buffer.getvalue()
image_view = vv.Image(png_bytes)
# Create a control panel
control_content = """
# Control Panel
This control panel appears in the bottom-left area.
- **Feature 1**: Some control option
- **Feature 2**: Another control option
- **Feature 3**: Yet another control option
"""
control_view = vv.Markdown(control_content)
# Create mountain layout items
items = [
vv.MountainLayoutItem(label="Sine Wave", view=ts_graph),
vv.MountainLayoutItem(label="Random Image", view=image_view),
vv.MountainLayoutItem(
label="Controls",
view=control_view,
is_control=True,
control_height=200
)
]
# Create the mountain layout
mountain_layout = vv.MountainLayout(items=items)
return mountain_layout
# Create and display the layout
layout = create_mountain_layout()
layout.show(title="Mountain Layout Example", open_in_browser=True)
Key Features
Left Panel: Contains view buttons (top) and control views (bottom)
Right Panel: Split into north and south tab workspaces
Interactive Tabs: Click view buttons to open views in the focused workspace
Tab Management: Views can be closed and reopened, with proper tab switching
Focus Indication: Visual feedback shows which workspace (north/south) is currently focused
Control Views: Special views marked with
is_control=True
appear in the bottom-left panel
MountainLayoutItem Properties
Each item in the mountain layout can have the following properties:
label
(required): Display name for the view buttonview
(required): The figpack view to containis_control
(optional): Whether this is a control view (appears in bottom panel)control_height
(optional): Height in pixels for control views
The MountainLayout is perfect for creating dashboard-like interfaces where users need to manage multiple views in an organized workspace environment.