Figure GUI
This document details the implementation of figpack’s figure GUI component and how to extend it with new view types.
Role in the Figpack Ecosystem
The figpack-figure component is the React-based web application that renders interactive figures in the browser. It serves as the data visualization engine for the figpack system:
Build Integration: The GUI is built from TypeScript/React source code into compiled static assets
Python Package Inclusion: These compiled assets are bundled into the Python figpack package
Figure Deployment: When Python code creates a figure using
show()
, the compiled GUI assets are copied into the figure directory alongside the Zarr dataSelf-Contained Figures: Each figure becomes a complete, portable web application containing both the rendering logic and data
This architecture enables figpack’s core feature: self-contained HTML bundles that can be shared, archived, and viewed without requiring a figpack installation.
Architecture Overview
The figpack-figure GUI is built on three key architectural principles:
Plugin-Based View System
Extensible: New view types can be added through plugins without modifying core code
Modular: Each view type is implemented as a separate React component
Registered: Plugins register their view components with a central registry
Remote Zarr Data Access
Efficient Loading: Data is loaded on-demand from Zarr arrays using chunk-based access
Large Dataset Support: For some view components, hierarchical downsampling enables smooth interaction with large datasets
Standardized Interface: All view components access data through consistent Zarr interfaces
React Component Architecture
Component Props: Views receive
zarrGroup
,width
,height
, andFPView
props (FPView allows nested views)State Management: Shared state (time ranges, selections) coordinated through React contexts
Responsive: Dynamic sizing and layout adaptation
Package Structure
The figpack-figure codebase uses a monorepo workspace structure with multiple interconnected packages:
figpack-figure/
├── src/ # Main application code
├── packages/
│ ├── figpack-plugin-sdk/ # Core interfaces and types
│ ├── figpack-main-plugin/ # Standard view components
│ ├── figpack-spike-sorting-plugin/ # Neurophysiology views
│ └── figpack-franklab-plugin/ # Lab-specific extensions
Package Roles
figpack-plugin-sdk: Defines core interfaces (
FPPlugin
,FPViewComponent
,FPViewComponentProps
) and Zarr typesfigpack-main-plugin: Implements standard views (TimeseriesGraph, Image, Markdown, layouts)
figpack-spike-sorting-plugin: Provides neurophysiology-specific visualizations
figpack-franklab-plugin: Contains lab-specific view components
Main application: Orchestrates plugin loading, data access, and rendering
Build Dependencies
The build system compiles packages in dependency order:
plugin-sdk builds first (provides interfaces)
Plugin packages build next (depend on SDK)
Main application builds last (depends on all plugins)
Plugin System
Core Plugin Interface
Plugins implement the FPPlugin
interface:
interface FPPlugin {
registerViewComponents: (registry: FPViewComponentRegistry) => void;
provideAppContexts?: (node: React.ReactNode) => React.ReactNode;
}
View Component Structure
Each view component implements FPViewComponent
:
interface FPViewComponent {
type: string; // Matches Python view_type
component: React.ComponentType<FPViewComponentProps>;
}
interface FPViewComponentProps {
zarrGroup: ZarrGroup; // Root data access
width: number; // Available width
height: number; // Available height
FPView: React.ComponentType; // For rendering nested views
}
Registration Process
Plugins register their view components during application startup:
// In plugin index file
const registerViewComponents = (registry: FPViewComponentRegistry) => {
registry.registerViewComponent({
type: "MyCustomView",
component: MyCustomViewComponent,
});
};
export default { registerViewComponents };
Creating View Components
Basic Component Structure
import { FPViewComponentProps } from "@figpack/plugin-sdk";
export const MyViewComponent: React.FC<FPViewComponentProps> = ({
zarrGroup,
width,
height,
}) => {
// Access view-specific attributes
const title = zarrGroup.attrs.title;
// Load data from Zarr datasets
// (see existing implementations for patterns)
return <div style={{ width, height }}>{/* Your view implementation */}</div>;
};
Data Access Patterns
View components access data through the zarrGroup
prop:
Attributes:
zarrGroup.attrs
contains view configurationDatasets: Use
zarrGroup.getDataset(path)
andgetDatasetData()
to access data arraysNested Groups: Use
zarrGroup.getGroup(path)
for hierarchical data
Common Patterns
Study existing view implementations for data loading patterns. For example:
TimeseriesGraph: Efficient line series rendering with downsampling
MultiChannelTimeseries: Large multi-channel data with virtual scrolling
Image: Binary data loading and display
Box/Splitter: Layout composition with nested views
Development Workflow
Setup
# Install dependencies
npm install
# Build all packages
npm run build
# Start development server
npm run dev
Development Commands
npm run dev
: Start development server with hot reloadnpm run build
: Build all packages for productionnpm run clean
: Clean all build artifactsnpm run format:all
: Format code with Prettier
Adding New Plugins
You can either add views to existing plugins or create new plugin packages. To create a new plugin:
Create Package: Add new package directory under
packages/
Implement Plugin: Create plugin following the
FPPlugin
interfaceRegister Plugin: Add to plugin list in
src/main.tsx
Update Build: Add build commands to root
package.json
Testing Integration
Local Development: Use
npm run dev
to test changes with hot reloadBuild Verification: Run
npm run build
to ensure production builds workPython Integration: Test with Python figpack package to verify end-to-end workflow (use _dev=True in
show()
)
Key Files for Learning
Essential Reading
packages/figpack-plugin-sdk/src/plugin-interface/FPPluginInterface.ts
: Core interfacespackages/figpack-main-plugin/src/index.tsx
: Plugin registration examplesrc/main.tsx
: Plugin loading and application setupsrc/App.tsx
: Main application structure
Example Implementations
packages/figpack-main-plugin/src/views/FPTimeseriesGraph.tsx
: Data visualizationpackages/figpack-main-plugin/src/views/FPBox.tsx
: Layout compositionpackages/figpack-main-plugin/src/views/FPImage.tsx
: Binary data handling