Writing pipeline files
A SciGraphs pipeline is a declarative JSON or YAML file that replays a whole workflow, dataset through export, with a fixed seed so results are reproducible. This page is the authoring reference.
Attach this file to whatever assistant you already use, Claude, ChatGPT, Copilot, a local model, then describe the figure you want and it replies with the specification.
It carries the field list generated from this same schema plus the rules a field list cannot express. Measured on ten requests against a 7B local model: none of the specifications it produced without this file were usable. With it and the schema below constraining the output, nine of ten both validated and matched the request.
One caution: a specification is not inert data. The ops block invokes arbitrary Blender operators, so read a generated file before running it.
Run one from the Reproducibility panel (Validate, then Run) or with the scigraphs.run_pipeline operator. Every field of every section, with its type, default and enum values, is listed in the auto-generated pipeline options reference; this page is about how to write a specification, that one is the exhaustive list.
Top-level structure
{
"meta": { "title": "my_pipeline", "seed": 42 },
"dataset": { "source": "osmnx", "method": "PLACE", "query": "Granada, Spain" },
"analysis": { "metrics": ["degree", "betweenness"] },
"layout": { "algorithm": "YIFAN_HU", "scale": 5.0 },
"visual": { "node_color": "betweenness", "color_norm": "RANK" },
"labels": { "rank_by": "betweenness", "max_count": 20 },
"world": { "color": [0.03, 0.03, 0.04], "strength": 1.0 },
"lighting": { "sun_energy": 3.0, "sun_angle": 180.0 },
"render": { "engine": "CYCLES", "output": "figure.png" },
"exports": { "graph": "network.gexf" },
"ops": [ { "id": "scigraphs.setup_lighting" } ]
}Only meta is required; the rest are optional and run in the order above. ops runs after lighting and before render. labels runs inside the render stage, after the camera is framed and before the image is produced, because it needs the final camera matrix.
Paths beginning with // resolve against the folder holding the specification, so a specification and its data travel together and the folder can be moved without editing anything.
meta
| Field | Type | Default | Notes |
|---|---|---|---|
title |
string | (required) | Pipeline identifier |
seed |
integer | 42 |
Global deterministic seed |
output_dir |
string | //repro/default |
Where artifacts are written |
clear_scene |
boolean | true |
Delete every existing object first, so the run does not depend on what the startup file contained |
description |
string | "" |
Human-readable description |
version |
string | "1.0" |
Pipeline version |
dataset
Choose one source. Each source uses a subset of the fields.
source |
Required fields | Optional fields |
|---|---|---|
osmnx |
query |
method (PLACE/BBOX/POINT/ADDRESS/POLYGON), network_type, simplify, cache, retain_all |
gexf / graphml / csv |
filepath |
auto_layout |
suitesparse |
matrix_name (e.g. Grund/bayer09) |
- |
sql |
- | nodes_query, edges_query, connection_string (the SQL profile is selected in the Data panel) |
city2graph |
query or bbox |
bbox is [west, south, east, north] |
network_type is one of drive, walk, bike, all, all_public, all_private, drive_service.
analysis
| Field | Type | Default | Notes |
|---|---|---|---|
metrics |
array of string | [] |
degree, betweenness, closeness, eigenvector, clustering |
clustering.algorithm |
string | infomap |
cpm, infomap, rb, rnsc, scluster, uvcluster (louvain/leiden are accepted and mapped to rb). rn was removed: it does not terminate even on a 77-node graph |
clustering.resolution |
number | 1.0 |
Higher = more communities |
normalize |
boolean | true |
Normalize centrality values |
Each metric is stored as a mesh attribute named centrality_<metric> (and clustering for the clustering coefficient); community labels go on cluster_id. Those names are what you reference from visual.
layout
| Field | Type | Default | Notes |
|---|---|---|---|
algorithm |
string | YIFAN_HU |
See the Layout panel for the full list |
scale |
number | 1.0 |
Overall layout scale |
iterations |
integer | 50 |
Iteration count (algorithm dependent) |
seed |
integer | meta.seed |
Per-layout seed override |
dimension |
integer | 3 |
2 or 3 |
k |
number | - | Ideal edge length (maps to sfdp_k or yifan_hu_spring_constant) |
gravity |
number | 1.0 |
Maps to fa2_gravity (ForceAtlas2) or gravity_strength |
scaling_ratio |
number | 2.0 |
ForceAtlas2 scaling ratio |
The dozens of algorithm-specific fa2_*, sfdp_*, igraph_* and graphviz_* properties are set through ops with nested scene_props, below.
visual
| Field | Type | Default | Notes |
|---|---|---|---|
setup_geometry_nodes |
boolean | true |
Build the Geometry Nodes visualization |
node_color |
string | - | Attribute name to color nodes by |
node_size |
string | - | Attribute name to size nodes by |
edge_width |
string | - | Attribute name to drive edge width |
edge_color |
string | - | Attribute name for edge coloring |
node_max_size |
number | 0.1 |
Upper bound for node sizing |
edge_max_width |
number | 0.02 |
Upper bound for edge width |
colormap |
string | viridis |
Any SciGraphs colormap |
edge_style |
string | - | GEPHI_DEFAULT, CYTOSCAPE_BEZIER, SCHEMATIC, BUNDLED_DENSE, FLOW_DIAGRAM, MINIMAL |
rendering_preset |
string | - | BASIC, GLASS, METALLIC, EMISSION, SCIENTIFIC |
Color mapping
color_norm is the field most worth knowing. A linear ramp over a heavy-tailed measure, betweenness or degree on a scale-free graph, drops almost every node into the darkest bin and the color channel stops carrying information. RANK equalizes the histogram and is the robust default for centrality; LOG keeps the shape of a smoothly varying quantity; QUANTILE ranks unique values rather than samples, which helps when many nodes tie. color_vmin/color_vmax pin an explicit domain so two figures share a scale, and they contradict RANK, which derives its own.
Glyph geometry and size
node_radius_rel and edge_radius_rel express radius as a fraction of the graph’s measured extent. Prefer them to the absolute forms, which are wrong at every scale but the one they were chosen for: a layout scaled to 50 units drawn with a 0.02 radius is subpixel at any framing. When both are given, the relative form wins.
node_glyph, node_resolution and edge_profile choose the primitive. Below about twelve segments the silhouette is visibly faceted in print.
render
| Field | Type | Default | Notes |
|---|---|---|---|
engine |
string | CYCLES |
CYCLES, BLENDER_EEVEE, BLENDER_WORKBENCH. EEVEE Next reclaimed the plain identifier in Blender 5.x; BLENDER_EEVEE_NEXT is rejected |
resolution |
[w, h] |
[1920, 1080] |
Output resolution |
samples |
integer | 128 |
Render samples |
camera |
string | - | Camera object name (active camera if omitted) |
output |
string | render.png |
Output filename (under output_dir) |
transparent |
boolean | false |
Transparent film |
denoise |
boolean | true |
Cycles denoising |
Camera, color management and engine
frame_camera places and aims a camera so the graph fills the frame; a named camera takes precedence. camera_ortho removes the near/far size falloff, so a node radius that encodes a value stays comparable across the frame.
view_transform matters more than it looks. Blender’s default is AgX, which tone-maps the image, so the rendered color of a node no longer equals the colormap entry for its value. Set Standard for anything color-quantitative.
Engine-specific fields are ignored by the other engine. Two are easy to get wrong: filter_width defaults to 1.5 px and visibly softens thin edges, and EEVEE’s ambient_occlusion does nothing without raytracing, since fast GI is a mode of the ray tracing pipeline. The executor enables the parent for you.
labels
Node labels composited over the render, ranked and decluttered. Runs inside the render stage, after the camera is framed, because the projection needs the final matrix.
Prefer max_count to min_value: the centrality attributes are normalized to [0,1], so a threshold that works on one graph is meaningless on the next, while a count is bounded whatever the size or distribution. occlusion hides labels whose node is behind geometry, and declutter drops labels that would overlap a higher-ranked one. Without it the renderer overdraws and dense regions become unreadable.
world
Background color, ambient strength, and an optional hdri. Untouched by default, in which case the render inherits whatever world the startup file carried, which is exactly the kind of undeclared dependency a specification exists to remove.
lighting
A single sun: sun_energy, sun_angle, sun_rotation and replace. One wide, soft key rather than a rig, because the graph is convex-ish and self-shadowing costs more legibility than the modeling it buys. A large sun_angle gives near-shadowless light that still separates glyphs by their own shading gradient.
exports
| Field | Type | Notes |
|---|---|---|
graph |
string | Filename; format inferred from extension (.gexf, .graphml, .json, .csv) |
positions |
string | Node positions CSV |
statistics |
string | Statistics report |
blend |
string | Save a .blend copy |
ops: the universal escape hatch
Anything the typed stages do not cover is reachable through ops, an ordered list of operator calls. Each entry has:
id: an operatorbl_idname(e.g.scigraphs.apply_layout) or a registry shortcut (e.g.layout,centrality,simplify).props: keyword arguments passed directly to the operator.scene_props: scene state to set before the call.
Nested scene_props by property group
scene_props may be flat (applied to scene.scigraphs) or nested by property group. Nesting is what makes every parameter reachable, including City2Graph, the coloring toolbar and the interactive visualization settings.
{
"id": "scigraphs.generate_proximity_graph",
"scene_props": {
"city2graph": { "prox_graph_type": "KNN", "prox_knn_k": 8 },
"coloring": { "colormap": "magma", "auto_range": true }
}
}| Group key | Scene property group |
|---|---|
scigraphs |
scene.scigraphs (graph, layout, OSMnx, splitter, edge style, text overlay) |
city2graph |
scene.city2graph (morphology, proximity, mobility, metapaths) |
coloring |
scene.scigraphs_coloring (coloring toolbar) |
viz |
scene.scigraphs_viz (interactive node/edge sizing) |
repro |
scene.scigraphs_repro |
splitter |
scene.scigraphs_splitter |
A flat scene_props with no group keys is still applied to scene.scigraphs for backward compatibility. For the always-current list of every property in every group, open the Reproducibility panel and click Export Options Reference.
Run artifacts
Each run writes, into output_dir:
pipeline.normalized.json- the fully resolved, canonical specification;run_manifest.json- provenance with input/output hashes and timing;run.log- the execution log, including any warnings.
Together with meta.seed, these make a run reproducible.
Examples
Six complete, ready-to-run specifications, with their renders and a note on the field each one exists to demonstrate, are in the reproducible-pipeline example. You can drag any of them straight onto the Blender viewport from that page.