Key Concepts

This page explains how Pixano organizes data. Understanding these concepts helps you design datasets, write import scripts, and get the most out of the UI.

Architecture overview

Pixano has three layers:

  • Python backend — manages datasets: creation, queries, updates, statistics. You can use it standalone for scripting.
  • REST API — a FastAPI server that exposes the backend over HTTP.
  • Web UI — a Svelte/TypeScript app for browsing, annotating, and running AI-assisted tools.

Run the full stack with pixano server run, or use the Python backend directly in your own scripts.

How data is organized

A Pixano dataset is a collection of tables stored in a LanceDB database. Each table belongs to one of seven schema groups:

GroupPurposeSchema classes
RecordOne row per dataset sample. Holds metadata, split, and workflow status.Record
ViewMedia files attached to a record.Image, Video, SequenceFrame, Text
EntityAn object observable in one or more views (e.g. a car, a person).Entity
AnnotationLabels attached to entities (bounding boxes, masks, keypoints, etc.).BBox, CompressedRLE, KeyPoints, MultiPath, Classification, TextSpan, Message, Tracklet
EntityDynamicStatePer-frame state of an entity in video (e.g. visibility, pose).EntityDynamicState
TimeseriesNumeric signals sampled alongside a record (e.g. robot state).Timeseries
EmbeddingVectors for semantic search.RecordEmbedding (record-level, used by the app), ViewEmbedding (legacy, per-view)

All schema classes live in pixano.schemas and are Pydantic models backed by LanceDB. You can subclass them to add custom fields.

Example: an object detection dataset

Consider an image dataset for detecting vehicles:

  1. Each record represents one image in the dataset (with a split like train or val).
  2. The record has one view — the image file itself.
  3. The image contains several entities — physical objects you want to label (a car, a truck, a bicycle).
  4. Each entity has one or more annotations — e.g. a bounding box with coordinates.
  5. You can later add model predictions (YOLO, GroundingDINO, etc.) as additional annotations — provenance fields on the annotation let you distinguish human labels from model outputs.
  6. You compute embeddings (e.g. OpenCLIP) so the dataset becomes searchable — those go in the embedding table.

The dataset schema

Every dataset is defined by a schema that declares its name, workspace type, views, and custom attributes. When importing, it lives in a dataset.yaml file:

pixano: 2
format: pixano_jsonl
dataset:
name: vehicle_detection
workspace: image
schema:
entity:
attrs:
category: str
annotations: [bbox]

The workspace selects the UI layout and provides default views. The annotations list determines which annotation tables are created in the database.

Custom fields

Records, entities, and per-frame states accept domain-specific attributes with a type and an optional default:

schema:
entity:
attrs:
category: str
is_difficult: { type: bool, default: false }
confidence: { type: float, default: 0.0 }

(Programmatic users can build the same schema in Python via DatasetInfo and Pydantic subclasses — the yaml compiles to exactly that.)

Record fields

The base Record class provides these fields out of the box:

FieldTypeDefaultDescription
idstr""Unique identifier for the record
splitstr"default"Dataset split (e.g. train, val, test)
statusstr"new"Workflow status: new, inProgress, inReview, validated
commentstr""Free-text note from the annotator
created_atdatetimenowCreation timestamp
updated_atdatetimenowLast modification timestamp

The status field is central to annotation campaigns: filter the dataset explorer by status to see which records still need work, and the Split and Status facets show how many fall into each bucket. You can set status in metadata.jsonl during import (e.g. "status": "validated" for ground truth).

Annotation provenance

No separate Source table

Provenance is tracked directly on annotations via three built-in fields: source_type (one of model, human, ground_truth, other), source_name, and source_metadata (a JSON string). This lets you distinguish human annotations from model predictions without a separate table.

Workspace types

The workspace type tells Pixano what kind of data you’re working with and which UI layout to display:

WorkspaceDataUI layout
IMAGESingle image per itemImage viewer with annotation tools
VIDEOFrame sequence per itemVideo player with timeline and track inspector
IMAGE_VQAImage + Q&A conversationsImage viewer + conversation panel
IMAGE_TEXT_ENTITY_LINKINGImage + textImage viewer + text panel with span selection

Directory structure

Pixano organizes data around three directories, created by pixano init:

my_data/
library/ # All datasets (each is a LanceDB database)
media/ # Images, videos, and other files referenced by views
models/ # Model files for inference (e.g. SAM weights)

Each dataset inside library/ has this layout:

library/<dataset>/
info.json # Name, description, workspace type, schema
features_values.json # Value constraints for fields
stats.json # Dataset statistics
embeddings.json # Semantic-search sidecar (model, dimension, metric)
previews/ # Generated thumbnails for the UI
db/ # LanceDB tables (one per schema)

Python API

from pathlib import Path
from pixano.datasets import Dataset
# Open a dataset
ds = Dataset(Path("./my_data/library/my_dataset"))
# Read records
records = ds.get_records(limit=20, skip=0)
# Read a specific table
images = ds.get_data("images", limit=5)
# Add annotations
ds.add_data("bboxes", [bbox1, bbox2])
# Semantic search over record embeddings. The query vector comes from the
# inference server; the app does this for you from the explorer's search bar.
records, distances = ds.search_records(query_vector, k=50)

Next steps

Pick a use case to see these concepts in action:

Esc