On this page

Historical material

This page preserves an earlier release or study. See the current guide for supported behavior.

Inklet v2

For nested layouts, publication presets and revision comparison, see the v2.5 guide.

V2 retains authoring instructions until compilation. A Document owns the page and theme; PlotSpec and ComponentSpec describe its contents. Compilation measures text and plot furniture, allocates cells, rebuilds plots at their final size, routes connections and resolves paint for SVG and PDF.

The existing Diagram, Panel and Figure APIs remain supported. Use them for fixed drawings, or place their output inside a document.

See diagrams for measured architecture modules, live data for filtered plots and derive() transformations, and release checks for reproducible validation.

A live plot

import inklet as i

data = i.dataset(
    {'time': [0, 1, 2], 'signal': [1, 3, 2]},
    units={'time': 's', 'signal': 'mV'},
    source=i.Source('Demonstration', method='simulated'),
)
p = i.plot_spec(x=(0, 2), y=i.shared_scale(data.column('signal')))
p.legend(side='bottom')  # Can be declared before the series.
p.axes(x='Time / s', y='Signal / mV', key='axes')
p.series(i.Series('Signal', data.column('time'), data.column('signal'), '#367ca4'))

doc = i.document(width=100)
doc.add('response', p, min_height=45)
first = doc.compile()

data.update(signal=[1, 3, 8])
p.replace('axes', x='Elapsed time / s', y='Measured signal / mV')
second = doc.compile()
second.export('out/review', name='response')

The second compilation uses the revised data and labels. first remains a snapshot of the earlier figure. Repeating doc.compile() without changes returns the same snapshot. Unchanged component geometry is reused when another cell changes.

Plot methods record their arguments. In 2.5, marks are built first, followed by axes, legends and colour bars, group labels and insets, brackets, callouts, and titles. Declaration order is preserved within each phase. key= names an instruction for replace() or remove(); it is not a drawing style. configure() changes plot scales, clipping and default dimensions. twin_x() and twin_y() return live instruction handles for the secondary axes.

Page layout

columns=2 creates two equally weighted tracks. columns=[1, 2] requests a 1:2 width allocation, adjusted as necessary to meet cell minima. Place cells with zero-based row and column; use rowspan and colspan to span tracks. Omitting row appends below the existing cells.

doc = i.document(width=180, columns=2, gap=6, margin=4)
doc.add('left', left_plot, row=0, column=0, min_width=60, min_height=45)
doc.add('right', right_plot, row=0, column=1, min_width=60, min_height=45)
doc.add('caption', caption_component, row=1, colspan=2, min_height=10)

The page width is fixed. With no page height, rows grow to fit their measured contents and minima. A fixed page height distributes available space across rows. Plot areas resize while text and strokes retain their physical sizes. Plots sharing a row or column share the relevant furniture margins. Existing Diagram and Panel inputs keep their authored dimensions.

Overlapping cells and unsatisfiable size constraints raise LayoutError with the available and required dimensions. Inklet does not shrink text or silently crop content to fit. Data outside a plot's domain is clipped only when you ask for clip=True, including in inset definitions.

Use doc.configure(width=150, theme='slides') to revise the page, and doc.replace('caption', new_component) to replace a cell while retaining its layout constraints. A radically narrower page may require changing the layout or reducing the number of columns; automatic editorial rearrangement is not part of the layout contract.

Components and connections

db = i.component(i.database, 'Sequence database', width=30)
matrix = i.component(i.feature_matrix, [[0.2, 0.8], [0.7, 0.1]], cell=6)
doc = i.document(width=120, columns=2)
doc.add('database', db, row=0, min_height=30)
doc.add('matrix', matrix, row=0, column=1, min_height=30)
doc.link('database:output', 'matrix:row-0')

Factories run under the document's theme. component.configure(...) revises arguments. Pass changing inputs explicitly: variables captured inside a Python closure are not tracked. Ordinary lists and dictionaries are snapshotted when recorded; Dataset, data references and other specs are live dependencies. For file-backed assets, pass i.FileRef(path) to the factory so a content change invalidates its cached drawing.

With responsive=True, a factory receives width and height keywords for its available cell. During natural-height measurement, height may be None. The factory must return a measurable Diagram. Repeated uses of the same component receive independent drawing identities. Link endpoints are cell names or cell:anchor strings; they resolve after layout.

Shared data definitions

Dataset.update() validates all changed columns together before applying an edit. Columns retain equal lengths, and a failed edit leaves the table intact. Use column(name) for one column and points(x, y) for paired coordinates.

shared_scale() computes a domain across one or more live numeric columns. The columns must have matching units and finite values. Linear and logarithmic scales are supported. Convert incompatible units explicitly before sharing a scale. Series supplies a name, colour, x/y values and optional absolute lower/upper uncertainty bounds; it draws a matching legend entry.

CategoryEncoding makes category selection live:

encoding = i.CategoryEncoding(i.categories(
    {'a': '#527da8', 'b': '#cb7853'},
    labels={'a': 'Control', 'b': 'Treatment'},
))
p = i.plot_spec(x=(0, 10), y=encoding.scale(reverse=True))
p.bars(data.column('condition'), data.column('value'),
       orient='h', bar_colors=encoding)
# Update the data and selection together before compiling.
encoding.select(['b'])

Axes, bar colours, keys and p.group_labels(encoding, ...) use the same selection. Unknown categories fail rather than silently receiving new colours.

Source records a citation and one of measured, digitized, simulated or illustrative. An optional source file is hashed when the record is created. The export manifest records data hashes, row counts, units, source records, font hashes, named cell bounds and compilation statistics. This records how a figure was made; it does not verify the scientific validity of the source.

Build and review

An author script should define make_document() and return a document. Scripts returning a Figure from make_figure() also work.

python -m inklet doctor
python -m inklet build examples/v2_document.py --output out/review
python -m inklet watch examples/v2_document.py --output out/review

The installed inklet command is equivalent to python -m inklet. doctor reports optional preview dependencies. Use build --vectors-only when Chrome and Poppler are unavailable, or --no-pdf-preview to omit the independent PDF preview. PNG output requires Pillow and Chrome/Chromium; PDF previews require Poppler.

watch serves on localhost and rebuilds in a fresh Python process when author code changes. Add --watch data.csv or --watch assets/ for data and assets. The previous successful bundle remains visible after a failed build; the page shows the error and resumes after the next successful edit. Use Ctrl-C to stop.

The review page includes SVG/PDF previews, the editable SVG and clickable spatial diagnostics. Clicking a finding opens and highlights its figure region. JSON diagnostics and the manifest are available alongside the exports.

See the complete live example, benchmark figures, and export options.

Search documentation

Type to search guides, examples and the API.